LLVM  8.0.1
RecordName.cpp
Go to the documentation of this file.
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 //===----------------------------------------------------------------------===//
9 
11 
12 #include "llvm/ADT/SmallString.h"
18 
19 using namespace llvm;
20 using namespace llvm::codeview;
21 
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();
27 
28  /// Name of the current type. Only valid before visitTypeEnd.
30 
31 public:
32  explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
33 
34  StringRef name() const { return Name; }
35 
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;
41 
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"
47 };
48 } // namespace
49 
50 Error TypeNameComputer::visitTypeBegin(CVType &Record) {
51  llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
52  return Error::success();
53 }
54 
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();
60 }
61 
62 Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
63 
66  Name = "<field list>";
67  return Error::success();
68 }
69 
71  StringIdRecord &String) {
72  Name = String.getString();
73  return Error::success();
74 }
75 
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);
82 
83  Name.append(Types.getTypeName(Indices[I]));
84  if (I + 1 != Size)
85  Name.append(", ");
86  }
87  Name.push_back(')');
88  return Error::success();
89 }
90 
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("\" \"");
100  }
101  Name.push_back('\"');
102  return Error::success();
103 }
104 
106  Name = Class.getName();
107  return Error::success();
108 }
109 
111  Name = Union.getName();
112  return Error::success();
113 }
114 
116  Name = Enum.getName();
117  return Error::success();
118 }
119 
121  Name = AT.getName();
122  return Error::success();
123 }
124 
126  Name = VFT.getName();
127  return Error::success();
128 }
129 
131  Name = Id.getName();
132  return Error::success();
133 }
134 
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();
140 }
141 
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();
149 }
150 
152  Name = Func.getName();
153  return Error::success();
154 }
155 
157  Name = TS.getName();
158  return Error::success();
159 }
160 
162 
163  if (Ptr.isPointerToMember()) {
164  const MemberPointerInfo &MI = Ptr.getMemberInfo();
165 
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()));
171 
173  Name.append("&");
174  else if (Ptr.getMode() == PointerMode::RValueReference)
175  Name.append("&&");
176  else if (Ptr.getMode() == PointerMode::Pointer)
177  Name.append("*");
178 
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");
189  }
190  return Error::success();
191 }
192 
194  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
195 
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();
204 }
205 
207  VFTableShapeRecord &Shape) {
208  Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
209  return Error::success();
210 }
211 
213  CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
214  return Error::success();
215 }
216 
218  UdtSourceLineRecord &SourceLine) {
219  return Error::success();
220 }
221 
223  return Error::success();
224 }
225 
227  MethodOverloadListRecord &Overloads) {
228  return Error::success();
229 }
230 
232  return Error::success();
233 }
234 
236  return Error::success();
237 }
238 
240  PrecompRecord &Precomp) {
241  return Error::success();
242 }
243 
245  EndPrecompRecord &EndPrecomp) {
246  return Error::success();
247 }
248 
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>";
256  }
257  return Computer.name();
258 }
259 
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;
315  }
316 }
317 
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.
323  // The container doesn't matter for single records.
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;
330  }
331 
332  int Offset = getSymbolNameOffset(Sym);
333  if (Offset == -1)
334  return StringRef();
335 
336  StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
337  return StringData.split('\0').first;
338 }
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:704
static int getSymbolNameOffset(CVSymbol Sym)
Definition: RecordName.cpp:260
Kind kind() const
Definition: CVRecord.h:37
This class represents lattice values for constants.
Definition: AllocatorList.h:24
virtual CVType getType(TypeIndex Index)=0
TypeIndex getReferentType() const
Definition: TypeRecord.h:304
MemberPointerInfo getMemberInfo() const
Definition: TypeRecord.h:324
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:249
StringRef getName() const
Definition: TypeRecord.h:460
amdgpu Simplify well known AMD library false Value Value const Twine & Name
StringRef getName() const
Definition: TypeRecord.h:626
StringRef getName() const
Definition: TypeRecord.h:414
ArrayRef< uint8_t > content() const
Definition: CVRecord.h:44
static Error visitKnownRecord(CVSymbol &Record, SymbolVisitorCallbacks &Callbacks)
PointerMode getMode() const
Definition: TypeRecord.h:311
A 32-bit type reference.
Definition: TypeIndex.h:96
TypeIndex getReturnType() const
Definition: TypeRecord.h:163
StringRef getString() const
Definition: TypeRecord.h:609
TypeIndex getContainingType() const
Definition: TypeRecord.h:115
TypeIndex getArgumentList() const
Definition: TypeRecord.h:167
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:53
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:982
#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:327
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:727
The access may modify the value stored in memory.
ArrayRef< TypeIndex > getIndices() const
Definition: TypeRecord.h:264
#define I(x, y, z)
Definition: MD5.cpp:58
ArrayRef< TypeIndex > getIndices() const
Definition: TypeRecord.h:250
uint32_t Size
Definition: Profile.cpp:47
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const char * name
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
TypeIndex getModifiedType() const
Definition: TypeRecord.h:144
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:49
static TypeIndex None()
Definition: TypeIndex.h:139
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
StringRef getSymbolName(CVSymbol Sym)
Definition: RecordName.cpp:318
StringRef getName() const
Definition: TypeRecord.h:713
ModifierOptions getModifiers() const
Definition: TypeRecord.h:145