LLVM  9.0.0svn
RecordName.cpp
Go to the documentation of this file.
1 //===- RecordName.cpp ----------------------------------------- *- 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 
10 
11 #include "llvm/ADT/SmallString.h"
17 
18 using namespace llvm;
19 using namespace llvm::codeview;
20 
21 namespace {
22 class TypeNameComputer : public TypeVisitorCallbacks {
23  /// The type collection. Used to calculate names of nested types.
24  TypeCollection &Types;
25  TypeIndex CurrentTypeIndex = TypeIndex::None();
26 
27  /// Name of the current type. Only valid before visitTypeEnd.
29 
30 public:
31  explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
32 
33  StringRef name() const { return Name; }
34 
35  /// Paired begin/end actions for all types. Receives all record data,
36  /// including the fixed-length record prefix.
37  Error visitTypeBegin(CVType &Record) override;
38  Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
39  Error visitTypeEnd(CVType &Record) override;
40 
41 #define TYPE_RECORD(EnumName, EnumVal, Name) \
42  Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
43 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
44 #define MEMBER_RECORD(EnumName, EnumVal, Name)
45 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
46 };
47 } // namespace
48 
49 Error TypeNameComputer::visitTypeBegin(CVType &Record) {
50  llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
51  return Error::success();
52 }
53 
54 Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
55  // Reset Name to the empty string. If the visitor sets it, we know it.
56  Name = "";
57  CurrentTypeIndex = Index;
58  return Error::success();
59 }
60 
61 Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
62 
65  Name = "<field list>";
66  return Error::success();
67 }
68 
70  StringIdRecord &String) {
71  Name = String.getString();
72  return Error::success();
73 }
74 
76  auto Indices = Args.getIndices();
77  uint32_t Size = Indices.size();
78  Name = "(";
79  for (uint32_t I = 0; I < Size; ++I) {
80  assert(Indices[I] < CurrentTypeIndex);
81 
82  Name.append(Types.getTypeName(Indices[I]));
83  if (I + 1 != Size)
84  Name.append(", ");
85  }
86  Name.push_back(')');
87  return Error::success();
88 }
89 
91  StringListRecord &Strings) {
92  auto Indices = Strings.getIndices();
93  uint32_t Size = Indices.size();
94  Name = "\"";
95  for (uint32_t I = 0; I < Size; ++I) {
96  Name.append(Types.getTypeName(Indices[I]));
97  if (I + 1 != Size)
98  Name.append("\" \"");
99  }
100  Name.push_back('\"');
101  return Error::success();
102 }
103 
105  Name = Class.getName();
106  return Error::success();
107 }
108 
110  Name = Union.getName();
111  return Error::success();
112 }
113 
115  Name = Enum.getName();
116  return Error::success();
117 }
118 
120  Name = AT.getName();
121  return Error::success();
122 }
123 
125  Name = VFT.getName();
126  return Error::success();
127 }
128 
130  Name = Id.getName();
131  return Error::success();
132 }
133 
135  StringRef Ret = Types.getTypeName(Proc.getReturnType());
136  StringRef Params = Types.getTypeName(Proc.getArgumentList());
137  Name = formatv("{0} {1}", Ret, Params).sstr<256>();
138  return Error::success();
139 }
140 
142  MemberFunctionRecord &MF) {
143  StringRef Ret = Types.getTypeName(MF.getReturnType());
144  StringRef Class = Types.getTypeName(MF.getClassType());
145  StringRef Params = Types.getTypeName(MF.getArgumentList());
146  Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
147  return Error::success();
148 }
149 
151  Name = Func.getName();
152  return Error::success();
153 }
154 
156  Name = TS.getName();
157  return Error::success();
158 }
159 
161 
162  if (Ptr.isPointerToMember()) {
163  const MemberPointerInfo &MI = Ptr.getMemberInfo();
164 
165  StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
166  StringRef Class = Types.getTypeName(MI.getContainingType());
167  Name = formatv("{0} {1}::*", Pointee, Class);
168  } else {
169  Name.append(Types.getTypeName(Ptr.getReferentType()));
170 
172  Name.append("&");
173  else if (Ptr.getMode() == PointerMode::RValueReference)
174  Name.append("&&");
175  else if (Ptr.getMode() == PointerMode::Pointer)
176  Name.append("*");
177 
178  // Qualifiers in pointer records apply to the pointer, not the pointee, so
179  // they go on the right.
180  if (Ptr.isConst())
181  Name.append(" const");
182  if (Ptr.isVolatile())
183  Name.append(" volatile");
184  if (Ptr.isUnaligned())
185  Name.append(" __unaligned");
186  if (Ptr.isRestrict())
187  Name.append(" __restrict");
188  }
189  return Error::success();
190 }
191 
193  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
194 
195  if (Mods & uint16_t(ModifierOptions::Const))
196  Name.append("const ");
197  if (Mods & uint16_t(ModifierOptions::Volatile))
198  Name.append("volatile ");
199  if (Mods & uint16_t(ModifierOptions::Unaligned))
200  Name.append("__unaligned ");
201  Name.append(Types.getTypeName(Mod.getModifiedType()));
202  return Error::success();
203 }
204 
206  VFTableShapeRecord &Shape) {
207  Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
208  return Error::success();
209 }
210 
212  CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
213  return Error::success();
214 }
215 
217  UdtSourceLineRecord &SourceLine) {
218  return Error::success();
219 }
220 
222  return Error::success();
223 }
224 
226  MethodOverloadListRecord &Overloads) {
227  return Error::success();
228 }
229 
231  return Error::success();
232 }
233 
235  return Error::success();
236 }
237 
239  PrecompRecord &Precomp) {
240  return Error::success();
241 }
242 
244  EndPrecompRecord &EndPrecomp) {
245  return Error::success();
246 }
247 
249  TypeIndex Index) {
250  TypeNameComputer Computer(Types);
251  CVType Record = Types.getType(Index);
252  if (auto EC = visitTypeRecord(Record, Index, Computer)) {
253  consumeError(std::move(EC));
254  return "<unknown UDT>";
255  }
256  return Computer.name();
257 }
258 
259 static int getSymbolNameOffset(CVSymbol Sym) {
260  switch (Sym.kind()) {
261  // See ProcSym
262  case SymbolKind::S_GPROC32:
263  case SymbolKind::S_LPROC32:
264  case SymbolKind::S_GPROC32_ID:
265  case SymbolKind::S_LPROC32_ID:
266  case SymbolKind::S_LPROC32_DPC:
267  case SymbolKind::S_LPROC32_DPC_ID:
268  return 35;
269  // See Thunk32Sym
270  case SymbolKind::S_THUNK32:
271  return 21;
272  // See SectionSym
273  case SymbolKind::S_SECTION:
274  return 16;
275  // See CoffGroupSym
276  case SymbolKind::S_COFFGROUP:
277  return 14;
278  // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
279  case SymbolKind::S_PUB32:
280  case SymbolKind::S_FILESTATIC:
281  case SymbolKind::S_REGREL32:
282  case SymbolKind::S_GDATA32:
283  case SymbolKind::S_LDATA32:
284  case SymbolKind::S_LMANDATA:
285  case SymbolKind::S_GMANDATA:
286  case SymbolKind::S_LTHREAD32:
287  case SymbolKind::S_GTHREAD32:
288  case SymbolKind::S_PROCREF:
289  case SymbolKind::S_LPROCREF:
290  return 10;
291  // See RegisterSym and LocalSym
292  case SymbolKind::S_REGISTER:
293  case SymbolKind::S_LOCAL:
294  return 6;
295  // See BlockSym
296  case SymbolKind::S_BLOCK32:
297  return 18;
298  // See LabelSym
299  case SymbolKind::S_LABEL32:
300  return 7;
301  // See ObjNameSym, ExportSym, and UDTSym
302  case SymbolKind::S_OBJNAME:
303  case SymbolKind::S_EXPORT:
304  case SymbolKind::S_UDT:
305  return 4;
306  // See BPRelativeSym
307  case SymbolKind::S_BPREL32:
308  return 8;
309  // See UsingNamespaceSym
310  case SymbolKind::S_UNAMESPACE:
311  return 0;
312  default:
313  return -1;
314  }
315 }
316 
318  if (Sym.kind() == SymbolKind::S_CONSTANT) {
319  // S_CONSTANT is preceded by an APSInt, which has a variable length. So we
320  // have to do a full deserialization.
322  // The container doesn't matter for single records.
324  ConstantSym Const(SymbolKind::S_CONSTANT);
325  cantFail(Mapping.visitSymbolBegin(Sym));
326  cantFail(Mapping.visitKnownRecord(Sym, Const));
327  cantFail(Mapping.visitSymbolEnd(Sym));
328  return Const.Name;
329  }
330 
331  int Offset = getSymbolNameOffset(Sym);
332  if (Offset == -1)
333  return StringRef();
334 
335  StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
336  return StringData.split('\0').first;
337 }
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:703
static int getSymbolNameOffset(CVSymbol Sym)
Definition: RecordName.cpp:259
Kind kind() const
Definition: CVRecord.h:43
This class represents lattice values for constants.
Definition: AllocatorList.h:23
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
virtual CVType getType(TypeIndex Index)=0
TypeIndex getReferentType() const
Definition: TypeRecord.h:303
MemberPointerInfo getMemberInfo() const
Definition: TypeRecord.h:323
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::string computeTypeName(TypeCollection &Types, TypeIndex Index)
Definition: RecordName.cpp:248
StringRef getName() const
Definition: TypeRecord.h:459
StringRef getName() const
Definition: TypeRecord.h:625
StringRef getName() const
Definition: TypeRecord.h:413
ArrayRef< uint8_t > content() const
Definition: CVRecord.h:57
static Error visitKnownRecord(CVSymbol &Record, SymbolVisitorCallbacks &Callbacks)
PointerMode getMode() const
Definition: TypeRecord.h:310
A 32-bit type reference.
Definition: TypeIndex.h:95
TypeIndex getReturnType() const
Definition: TypeRecord.h:162
StringRef getString() const
Definition: TypeRecord.h:608
TypeIndex getContainingType() const
Definition: TypeRecord.h:114
TypeIndex getArgumentList() const
Definition: TypeRecord.h:166
Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
Definition: StringExtras.h:52
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:981
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:696
The access may modify the value stored in memory.
ArrayRef< TypeIndex > getIndices() const
Definition: TypeRecord.h:263
#define I(x, y, z)
Definition: MD5.cpp:58
ArrayRef< TypeIndex > getIndices() const
Definition: TypeRecord.h:249
uint32_t Size
Definition: Profile.cpp:46
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const char * name
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
TypeIndex getModifiedType() const
Definition: TypeRecord.h:143
IRTranslator LLVM IR MI
Provides read only access to a subclass of BinaryStream.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
static TypeIndex None()
Definition: TypeIndex.h:138
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
StringRef getSymbolName(CVSymbol Sym)
Definition: RecordName.cpp:317
StringRef getName() const
Definition: TypeRecord.h:712
ModifierOptions getModifiers() const
Definition: TypeRecord.h:144