blob: 2eb8b81862f3c4a8a5dceaf327bbf67d117e0b88 [file] [log] [blame]
//===- TypeName.cpp ------------------------------------------- *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/TypeName.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/FormatVariadic.h"
using namespace llvm;
using namespace llvm::codeview;
namespace {
class TypeNameComputer : public TypeVisitorCallbacks {
/// The type collection. Used to calculate names of nested types.
TypeCollection &Types;
TypeIndex CurrentTypeIndex = TypeIndex::None();
/// Name of the current type. Only valid before visitTypeEnd.
SmallString<256> Name;
public:
explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
StringRef name() const { return Name; }
/// Paired begin/end actions for all types. Receives all record data,
/// including the fixed-length record prefix.
Error visitTypeBegin(CVType &Record) override;
Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
Error visitTypeEnd(CVType &Record) override;
#define TYPE_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name)
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
};
} // namespace
Error TypeNameComputer::visitTypeBegin(CVType &Record) {
llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
return Error::success();
}
Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
// Reset Name to the empty string. If the visitor sets it, we know it.
Name = "";
CurrentTypeIndex = Index;
return Error::success();
}
Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
FieldListRecord &FieldList) {
Name = "<field list>";
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
StringIdRecord &String) {
Name = String.getString();
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
auto Indices = Args.getIndices();
uint32_t Size = Indices.size();
Name = "(";
for (uint32_t I = 0; I < Size; ++I) {
assert(Indices[I] < CurrentTypeIndex);
Name.append(Types.getTypeName(Indices[I]));
if (I + 1 != Size)
Name.append(", ");
}
Name.push_back(')');
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
StringListRecord &Strings) {
auto Indices = Strings.getIndices();
uint32_t Size = Indices.size();
Name = "\"";
for (uint32_t I = 0; I < Size; ++I) {
Name.append(Types.getTypeName(Indices[I]));
if (I + 1 != Size)
Name.append("\" \"");
}
Name.push_back('\"');
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
Name = Class.getName();
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
Name = Union.getName();
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
Name = Enum.getName();
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
Name = AT.getName();
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
Name = VFT.getName();
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
Name = Id.getName();
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
StringRef Ret = Types.getTypeName(Proc.getReturnType());
StringRef Params = Types.getTypeName(Proc.getArgumentList());
Name = formatv("{0} {1}", Ret, Params).sstr<256>();
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
MemberFunctionRecord &MF) {
StringRef Ret = Types.getTypeName(MF.getReturnType());
StringRef Class = Types.getTypeName(MF.getClassType());
StringRef Params = Types.getTypeName(MF.getArgumentList());
Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
Name = Func.getName();
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
Name = TS.getName();
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
if (Ptr.isPointerToMember()) {
const MemberPointerInfo &MI = Ptr.getMemberInfo();
StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
StringRef Class = Types.getTypeName(MI.getContainingType());
Name = formatv("{0} {1}::*", Pointee, Class);
} else {
if (Ptr.isConst())
Name.append("const ");
if (Ptr.isVolatile())
Name.append("volatile ");
if (Ptr.isUnaligned())
Name.append("__unaligned ");
Name.append(Types.getTypeName(Ptr.getReferentType()));
if (Ptr.getMode() == PointerMode::LValueReference)
Name.append("&");
else if (Ptr.getMode() == PointerMode::RValueReference)
Name.append("&&");
else if (Ptr.getMode() == PointerMode::Pointer)
Name.append("*");
}
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
SmallString<256> TypeName;
if (Mods & uint16_t(ModifierOptions::Const))
Name.append("const ");
if (Mods & uint16_t(ModifierOptions::Volatile))
Name.append("volatile ");
if (Mods & uint16_t(ModifierOptions::Unaligned))
Name.append("__unaligned ");
Name.append(Types.getTypeName(Mod.getModifiedType()));
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
VFTableShapeRecord &Shape) {
Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(
CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
UdtSourceLineRecord &SourceLine) {
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
MethodOverloadListRecord &Overloads) {
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
return Error::success();
}
Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
return Error::success();
}
std::string llvm::codeview::computeTypeName(TypeCollection &Types,
TypeIndex Index) {
TypeNameComputer Computer(Types);
CVType Record = Types.getType(Index);
if (auto EC = visitTypeRecord(Record, Index, Computer)) {
consumeError(std::move(EC));
return "<unknown UDT>";
}
return Computer.name();
}