From: Zachary Turner Date: Thu, 16 Jun 2016 18:09:04 +0000 (+0000) Subject: Revert "[pdb] Change type visitor pattern to be dynamic." X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=575a9fbcc90976539fb7225c07cb14141aba7fa0;p=llvm Revert "[pdb] Change type visitor pattern to be dynamic." This reverts commit fb0dd311e1ad945827b8ffd5354f4810e2be1579. This breaks some llvm-readobj tests. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@272927 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h index 930ac6930c2..fe0e1efe41b 100644 --- a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -11,31 +11,151 @@ #define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H #include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" -#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorOr.h" namespace llvm { namespace codeview { +template class CVTypeVisitor { public: - explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks); + CVTypeVisitor() {} - Error visitTypeRecord(const CVRecord &Record); + bool hadError() const { return HadError; } + + template + bool consumeObject(ArrayRef &Data, const T *&Res) { + if (Data.size() < sizeof(*Res)) { + HadError = true; + return false; + } + Res = reinterpret_cast(Data.data()); + Data = Data.drop_front(sizeof(*Res)); + return true; + } + + /// Actions to take on known types. By default, they do nothing. Visit methods + /// for member records take the FieldData by non-const reference and are + /// expected to consume the trailing bytes used by the field. + /// FIXME: Make the visitor interpret the trailing bytes so that clients don't + /// need to. +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + void visit##Name(Name##Record &Record) {} +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + void visit##Name(Name##Record &Record) {} +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "TypeRecords.def" + + void visitTypeRecord(const CVRecord &Record) { + ArrayRef LeafData = Record.Data; + auto *DerivedThis = static_cast(this); + DerivedThis->visitTypeBegin(Record); + switch (Record.Type) { + default: + DerivedThis->visitUnknownType(Record); + break; + case LF_FIELDLIST: + DerivedThis->visitFieldList(Record.Type, LeafData); + break; +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + case EnumName: { \ + TypeRecordKind RK = static_cast(EnumName); \ + auto Result = Name##Record::deserialize(RK, LeafData); \ + if (Result.getError()) \ + return parseError(); \ + DerivedThis->visit##Name(*Result); \ + break; \ + } +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ + TYPE_RECORD(EnumVal, EnumVal, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) +#include "TypeRecords.def" + } + DerivedThis->visitTypeEnd(Record); + } /// Visits the type records in Data. Sets the error flag on parse failures. - Error visitTypeStream(const CVTypeArray &Types); + void visitTypeStream(const CVTypeArray &Types) { + for (const auto &I : Types) { + visitTypeRecord(I); + if (hadError()) + break; + } + } + + /// Action to take on unknown types. By default, they are ignored. + void visitUnknownType(const CVRecord &Record) {} - Error skipPadding(ArrayRef &Data); + /// Paired begin/end actions for all types. Receives all record data, + /// including the fixed-length record prefix. + void visitTypeBegin(const CVRecord &Record) {} + void visitTypeEnd(const CVRecord &Record) {} + + ArrayRef skipPadding(ArrayRef Data) { + if (Data.empty()) + return Data; + uint8_t Leaf = Data.front(); + if (Leaf < LF_PAD0) + return Data; + // Leaf is greater than 0xf0. We should advance by the number of bytes in + // the low 4 bits. + unsigned BytesToAdvance = Leaf & 0x0F; + if (Data.size() < BytesToAdvance) { + parseError(); + return None; + } + return Data.drop_front(BytesToAdvance); + } /// Visits individual member records of a field list record. Member records do /// not describe their own length, and need special handling. - Error visitFieldList(const CVRecord &Record); + void visitFieldList(TypeLeafKind Leaf, ArrayRef FieldData) { + auto *DerivedThis = static_cast(this); + while (!FieldData.empty()) { + const ulittle16_t *LeafPtr; + if (!CVTypeVisitor::consumeObject(FieldData, LeafPtr)) + return; + TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr)); + switch (Leaf) { + default: + // Field list records do not describe their own length, so we cannot + // continue parsing past an unknown member type. + DerivedThis->visitUnknownMember(Leaf); + return parseError(); +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + case EnumName: { \ + TypeRecordKind RK = static_cast(EnumName); \ + auto Result = Name##Record::deserialize(RK, FieldData); \ + if (Result.getError()) \ + return parseError(); \ + DerivedThis->visit##Name(*Result); \ + break; \ + } +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ + MEMBER_RECORD(EnumVal, EnumVal, AliasName) +#include "TypeRecords.def" + } + FieldData = skipPadding(FieldData); + if (hadError()) + break; + } + } + + /// Action to take on unknown members. By default, they are ignored. Member + /// record parsing cannot recover from an unknown member record, so this + /// method is only called at most once per field list record. + void visitUnknownMember(TypeLeafKind Leaf) {} + + /// Helper for returning from a void function when the stream is corrupted. + void parseError() { HadError = true; } private: - /// The interface to the class that gets notified of each visitation. - TypeVisitorCallbacks &Callbacks; + /// Whether a type stream parsing error was encountered. + bool HadError = false; }; } // end namespace codeview diff --git a/include/llvm/DebugInfo/CodeView/TypeDumper.h b/include/llvm/DebugInfo/CodeView/TypeDumper.h index ca79ab076e5..a5e359fd586 100644 --- a/include/llvm/DebugInfo/CodeView/TypeDumper.h +++ b/include/llvm/DebugInfo/CodeView/TypeDumper.h @@ -14,7 +14,6 @@ #include "llvm/ADT/StringSet.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" namespace llvm { class ScopedPrinter; @@ -22,7 +21,7 @@ class ScopedPrinter; namespace codeview { /// Dumper for CodeView type streams found in COFF object files and PDB files. -class CVTypeDumper : public TypeVisitorCallbacks { +class CVTypeDumper { public: CVTypeDumper(ScopedPrinter *W, bool PrintRecordBytes) : W(W), PrintRecordBytes(PrintRecordBytes) {} @@ -34,17 +33,17 @@ public: /// and true otherwise. This should be called in order, since the dumper /// maintains state about previous records which are necessary for cross /// type references. - Error dump(const CVRecord &Record); + bool dump(const CVRecord &Record); /// Dumps the type records in Types. Returns false if there was a type stream /// parse error, and true otherwise. - Error dump(const CVTypeArray &Types); + bool dump(const CVTypeArray &Types); /// Dumps the type records in Data. Returns false if there was a type stream /// parse error, and true otherwise. Use this method instead of the /// CVTypeArray overload when type records are laid out contiguously in /// memory. - Error dump(ArrayRef Data); + bool dump(ArrayRef Data); /// Gets the type index for the next type record. unsigned getNextTypeIndex() const { @@ -62,35 +61,11 @@ public: void setPrinter(ScopedPrinter *P); ScopedPrinter *getPrinter() { return W; } - /// Action to take on unknown types. By default, they are ignored. - Error visitUnknownType(const CVRecord &Record) override; - Error visitUnknownMember(const CVRecord &Record) override; - - /// Paired begin/end actions for all types. Receives all record data, - /// including the fixed-length record prefix. - Error visitTypeBegin(const CVRecord &Record) override; - Error visitTypeEnd(const CVRecord &Record) override; - -#define TYPE_RECORD(EnumName, EnumVal, Name) \ - Error visit##Name(Name##Record &Record) override; -#define MEMBER_RECORD(EnumName, EnumVal, Name) \ - TYPE_RECORD(EnumName, EnumVal, Name) -#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "TypeRecords.def" - private: - void printMemberAttributes(MemberAttributes Attrs); - void printMemberAttributes(MemberAccess Access, MethodKind Kind, - MethodOptions Options); - ScopedPrinter *W; bool PrintRecordBytes = false; - /// Name of the current type. Only valid before visitTypeEnd. - StringRef Name; - /// All user defined type records in .debug$T live in here. Type indices /// greater than 0x1000 are user defined. Subtract 0x1000 from the index to /// index into this vector. diff --git a/include/llvm/DebugInfo/CodeView/TypeRecords.def b/include/llvm/DebugInfo/CodeView/TypeRecords.def index 41fbeaa5be6..5f10b72c530 100644 --- a/include/llvm/DebugInfo/CodeView/TypeRecords.def +++ b/include/llvm/DebugInfo/CodeView/TypeRecords.def @@ -83,7 +83,6 @@ TYPE_RECORD(LF_STRING_ID, 0x1605, StringId) TYPE_RECORD(LF_UDT_SRC_LINE, 0x1606, UdtSourceLine) TYPE_RECORD(LF_UDT_MOD_SRC_LINE, 0x1607, UdtModSourceLine) - TYPE_RECORD(LF_METHODLIST, 0x1206, MethodOverloadList) @@ -196,8 +195,6 @@ CV_TYPE(LF_MODIFIER_EX, 0x1518) CV_TYPE(LF_VECTOR, 0x151b) CV_TYPE(LF_MATRIX, 0x151c) -// ID leaf records. Subsequent leaf types may be referenced from .debug$S. - // Numeric leaf types. These are generally contained in other records, and not // encountered in the main type stream. diff --git a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h deleted file mode 100644 index db734646971..00000000000 --- a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h +++ /dev/null @@ -1,53 +0,0 @@ -//===- TypeVisitorCallbacks.h -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKS_H -#define LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKS_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/Support/Error.h" - -namespace llvm { -namespace codeview { -class TypeVisitorCallbacks { - friend class CVTypeVisitor; - -public: - virtual ~TypeVisitorCallbacks() {} - - /// Action to take on unknown types. By default, they are ignored. - virtual Error visitUnknownType(const CVRecord &Record) { - return Error::success(); - } - virtual Error visitUnknownMember(const CVRecord &Record) { - return Error::success(); - } - - /// Paired begin/end actions for all types. Receives all record data, - /// including the fixed-length record prefix. - virtual Error visitTypeBegin(const CVRecord &Record) { - return Error::success(); - } - virtual Error visitTypeEnd(const CVRecord &Record) { - return Error::success(); - } - -#define TYPE_RECORD(EnumName, EnumVal, Name) \ - virtual Error visit##Name(Name##Record &Record) { return Error::success(); } -#define MEMBER_RECORD(EnumName, EnumVal, Name) \ - TYPE_RECORD(EnumName, EnumVal, Name) -#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "TypeRecords.def" -}; -} -} - -#endif \ No newline at end of file diff --git a/include/llvm/DebugInfo/PDB/Raw/RawError.h b/include/llvm/DebugInfo/PDB/Raw/RawError.h index b0687cddbf4..076f75ba031 100644 --- a/include/llvm/DebugInfo/PDB/Raw/RawError.h +++ b/include/llvm/DebugInfo/PDB/Raw/RawError.h @@ -25,7 +25,6 @@ enum class raw_error_code { index_out_of_bounds, invalid_block_address, not_writable, - invalid_tpi_hash, }; /// Base class for errors originating when parsing raw PDB files diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index d798901be1c..ff719b242c4 100644 --- a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -322,9 +322,10 @@ void CodeViewDebug::emitTypeInformation() { ScopedPrinter SP(CommentOS); SP.setPrefix(CommentPrefix); CVTD.setPrinter(&SP); - Error EC = CVTD.dump({Record.bytes_begin(), Record.bytes_end()}); - assert(!EC && "produced malformed type record"); - consumeError(std::move(EC)); + bool DumpSuccess = + CVTD.dump({Record.bytes_begin(), Record.bytes_end()}); + (void)DumpSuccess; + assert(DumpSuccess && "produced malformed type record"); // emitRawComment will insert its own tab and comment string before // the first line, so strip off our first one. It also prints its own // newline. diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt index 47297a9131e..4393f9c52ee 100644 --- a/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/lib/DebugInfo/CodeView/CMakeLists.txt @@ -1,7 +1,6 @@ add_llvm_library(LLVMDebugInfoCodeView ByteStream.cpp CodeViewError.cpp - CVTypeVisitor.cpp EnumTables.cpp FieldListRecordBuilder.cpp Line.cpp diff --git a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp deleted file mode 100644 index a22d9631795..00000000000 --- a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ /dev/null @@ -1,119 +0,0 @@ -//===- CVTypeVisitor.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/CVTypeVisitor.h" - -using namespace llvm; -using namespace llvm::codeview; - -template -static Error takeObject(ArrayRef &Data, const T *&Res) { - if (Data.size() < sizeof(*Res)) - return llvm::make_error(cv_error_code::insufficient_buffer); - Res = reinterpret_cast(Data.data()); - Data = Data.drop_front(sizeof(*Res)); - return Error::success(); -} - -CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks) - : Callbacks(Callbacks) {} - -Error CVTypeVisitor::visitTypeRecord(const CVRecord &Record) { - ArrayRef LeafData = Record.Data; - if (auto EC = Callbacks.visitTypeBegin(Record)) - return EC; - switch (Record.Type) { - default: - if (auto EC = Callbacks.visitUnknownType(Record)) - return EC; - break; - case LF_FIELDLIST: - if (auto EC = visitFieldList(Record)) - return EC; - break; -#define TYPE_RECORD(EnumName, EnumVal, Name) \ - case EnumName: { \ - TypeRecordKind RK = static_cast(EnumName); \ - auto Result = Name##Record::deserialize(RK, LeafData); \ - if (Result.getError()) \ - return llvm::make_error(cv_error_code::corrupt_record); \ - if (auto EC = Callbacks.visit##Name(*Result)) \ - return EC; \ - break; \ - } -#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ - TYPE_RECORD(EnumVal, EnumVal, AliasName) -#define MEMBER_RECORD(EnumName, EnumVal, Name) -#include "llvm/DebugInfo/CodeView/TypeRecords.def" - } - if (auto EC = Callbacks.visitTypeEnd(Record)) - return EC; - return Error::success(); -} - -/// Visits the type records in Data. Sets the error flag on parse failures. -Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) { - for (const auto &I : Types) { - if (auto EC = visitTypeRecord(I)) - return EC; - } - return Error::success(); -} - -Error CVTypeVisitor::skipPadding(ArrayRef &Data) { - if (Data.empty()) - return Error::success(); - uint8_t Leaf = Data.front(); - if (Leaf < LF_PAD0) - return Error::success(); - // Leaf is greater than 0xf0. We should advance by the number of bytes in - // the low 4 bits. - unsigned BytesToAdvance = Leaf & 0x0F; - if (Data.size() < BytesToAdvance) { - return llvm::make_error(cv_error_code::corrupt_record, - "Invalid padding bytes!"); - } - Data = Data.drop_front(BytesToAdvance); - return Error::success(); -} - -/// Visits individual member records of a field list record. Member records do -/// not describe their own length, and need special handling. -Error CVTypeVisitor::visitFieldList(const CVRecord &Record) { - ArrayRef RecordData = Record.Data; - while (!RecordData.empty()) { - const ulittle16_t *LeafPtr; - if (auto EC = takeObject(RecordData, LeafPtr)) - return EC; - TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr)); - switch (Leaf) { - default: - // Field list records do not describe their own length, so we cannot - // continue parsing past an unknown member type. - if (auto EC = Callbacks.visitUnknownMember(Record)) - return llvm::make_error(cv_error_code::corrupt_record); -#define MEMBER_RECORD(EnumName, EnumVal, Name) \ - case EnumName: { \ - TypeRecordKind RK = static_cast(EnumName); \ - auto Result = Name##Record::deserialize(RK, RecordData); \ - if (Result.getError()) \ - return llvm::make_error(cv_error_code::corrupt_record); \ - if (auto EC = Callbacks.visit##Name(*Result)) \ - return EC; \ - break; \ - } -#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ - MEMBER_RECORD(EnumVal, EnumVal, AliasName) -#include "llvm/DebugInfo/CodeView/TypeRecords.def" - } - if (auto EC = skipPadding(RecordData)) - return EC; - } - return Error::success(); -} diff --git a/lib/DebugInfo/CodeView/TypeDumper.cpp b/lib/DebugInfo/CodeView/TypeDumper.cpp index 0653d814155..b181ffb7c4d 100644 --- a/lib/DebugInfo/CodeView/TypeDumper.cpp +++ b/lib/DebugInfo/CodeView/TypeDumper.cpp @@ -189,6 +189,55 @@ static const EnumEntry FunctionOptionEnum[] = { #undef ENUM_ENTRY + +namespace { + +/// Use this private dumper implementation to keep implementation details about +/// the visitor out of TypeDumper.h. +class CVTypeDumperImpl : public CVTypeVisitor { +public: + CVTypeDumperImpl(CVTypeDumper &CVTD, ScopedPrinter &W, bool PrintRecordBytes) + : CVTD(CVTD), W(W), PrintRecordBytes(PrintRecordBytes) {} + + /// CVTypeVisitor overrides. +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + void visit##Name(Name##Record &Record); +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + void visit##Name(Name##Record &Record); +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "llvm/DebugInfo/CodeView/TypeRecords.def" + + void visitUnknownMember(TypeLeafKind Leaf); + void visitUnknownType(const CVRecord &Record); + + void visitTypeBegin(const CVRecord &Record); + void visitTypeEnd(const CVRecord &Record); + + void printMemberAttributes(MemberAttributes Attrs); + void printMemberAttributes(MemberAccess Access, MethodKind Kind, + MethodOptions Options); + +private: + /// Forwards to the dumper, which holds the persistent state from visitation. + StringRef getTypeName(TypeIndex TI) { + return CVTD.getTypeName(TI); + } + + void printTypeIndex(StringRef FieldName, TypeIndex TI) { + CVTD.printTypeIndex(FieldName, TI); + } + + CVTypeDumper &CVTD; + ScopedPrinter &W; + bool PrintRecordBytes = false; + + /// Name of the current type. Only valid before visitTypeEnd. + StringRef Name; +}; + +} // end anonymous namespace + static StringRef getLeafTypeName(TypeLeafKind LT) { switch (LT) { #define TYPE_RECORD(ename, value, name) \ @@ -201,44 +250,39 @@ static StringRef getLeafTypeName(TypeLeafKind LT) { return "UnknownLeaf"; } -Error CVTypeDumper::visitTypeBegin(const CVRecord &Record) { +void CVTypeDumperImpl::visitTypeBegin(const CVRecord &Rec) { // Reset Name to the empty string. If the visitor sets it, we know it. Name = ""; - W->startLine() << getLeafTypeName(Record.Type) << " (" - << HexNumber(getNextTypeIndex()) << ") {\n"; - W->indent(); - W->printEnum("TypeLeafKind", unsigned(Record.Type), - makeArrayRef(LeafTypeNames)); - return Error::success(); + W.startLine() << getLeafTypeName(Rec.Type) << " (" + << HexNumber(CVTD.getNextTypeIndex()) << ") {\n"; + W.indent(); + W.printEnum("TypeLeafKind", unsigned(Rec.Type), makeArrayRef(LeafTypeNames)); } -Error CVTypeDumper::visitTypeEnd(const CVRecord &Record) { +void CVTypeDumperImpl::visitTypeEnd(const CVRecord &Rec) { // Always record some name for every type, even if Name is empty. CVUDTNames // is indexed by type index, and must have one entry for every type. - recordType(Name); - + CVTD.recordType(Name); if (PrintRecordBytes) - W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data)); + W.printBinaryBlock("LeafData", getBytesAsCharacters(Rec.Data)); - W->unindent(); - W->startLine() << "}\n"; - return Error::success(); + W.unindent(); + W.startLine() << "}\n"; } -Error CVTypeDumper::visitStringId(StringIdRecord &String) { +void CVTypeDumperImpl::visitStringId(StringIdRecord &String) { printTypeIndex("Id", String.getId()); - W->printString("StringData", String.getString()); + W.printString("StringData", String.getString()); // Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE. Name = String.getString(); - return Error::success(); } -Error CVTypeDumper::visitArgList(ArgListRecord &Args) { +void CVTypeDumperImpl::visitArgList(ArgListRecord &Args) { auto Indices = Args.getIndices(); uint32_t Size = Indices.size(); - W->printNumber("NumArgs", Size); - ListScope Arguments(*W, "Arguments"); + W.printNumber("NumArgs", Size); + ListScope Arguments(W, "Arguments"); SmallString<256> TypeName("("); for (uint32_t I = 0; I < Size; ++I) { printTypeIndex("ArgType", Indices[I]); @@ -248,84 +292,77 @@ Error CVTypeDumper::visitArgList(ArgListRecord &Args) { TypeName.append(", "); } TypeName.push_back(')'); - Name = saveName(TypeName); - return Error::success(); + Name = CVTD.saveName(TypeName); } -Error CVTypeDumper::visitClass(ClassRecord &Class) { +void CVTypeDumperImpl::visitClass(ClassRecord &Class) { uint16_t Props = static_cast(Class.getOptions()); - W->printNumber("MemberCount", Class.getMemberCount()); - W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames)); + W.printNumber("MemberCount", Class.getMemberCount()); + W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames)); printTypeIndex("FieldList", Class.getFieldList()); printTypeIndex("DerivedFrom", Class.getDerivationList()); printTypeIndex("VShape", Class.getVTableShape()); - W->printNumber("SizeOf", Class.getSize()); - W->printString("Name", Class.getName()); + W.printNumber("SizeOf", Class.getSize()); + W.printString("Name", Class.getName()); if (Props & uint16_t(ClassOptions::HasUniqueName)) - W->printString("LinkageName", Class.getUniqueName()); + W.printString("LinkageName", Class.getUniqueName()); Name = Class.getName(); - return Error::success(); } -Error CVTypeDumper::visitUnion(UnionRecord &Union) { +void CVTypeDumperImpl::visitUnion(UnionRecord &Union) { uint16_t Props = static_cast(Union.getOptions()); - W->printNumber("MemberCount", Union.getMemberCount()); - W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames)); + W.printNumber("MemberCount", Union.getMemberCount()); + W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames)); printTypeIndex("FieldList", Union.getFieldList()); - W->printNumber("SizeOf", Union.getSize()); - W->printString("Name", Union.getName()); + W.printNumber("SizeOf", Union.getSize()); + W.printString("Name", Union.getName()); if (Props & uint16_t(ClassOptions::HasUniqueName)) - W->printString("LinkageName", Union.getUniqueName()); + W.printString("LinkageName", Union.getUniqueName()); Name = Union.getName(); - return Error::success(); } -Error CVTypeDumper::visitEnum(EnumRecord &Enum) { - W->printNumber("NumEnumerators", Enum.getMemberCount()); - W->printFlags("Properties", uint16_t(Enum.getOptions()), - makeArrayRef(ClassOptionNames)); +void CVTypeDumperImpl::visitEnum(EnumRecord &Enum) { + W.printNumber("NumEnumerators", Enum.getMemberCount()); + W.printFlags("Properties", uint16_t(Enum.getOptions()), + makeArrayRef(ClassOptionNames)); printTypeIndex("UnderlyingType", Enum.getUnderlyingType()); printTypeIndex("FieldListType", Enum.getFieldList()); - W->printString("Name", Enum.getName()); + W.printString("Name", Enum.getName()); Name = Enum.getName(); - return Error::success(); } -Error CVTypeDumper::visitArray(ArrayRecord &AT) { +void CVTypeDumperImpl::visitArray(ArrayRecord &AT) { printTypeIndex("ElementType", AT.getElementType()); printTypeIndex("IndexType", AT.getIndexType()); - W->printNumber("SizeOf", AT.getSize()); - W->printString("Name", AT.getName()); + W.printNumber("SizeOf", AT.getSize()); + W.printString("Name", AT.getName()); Name = AT.getName(); - return Error::success(); } -Error CVTypeDumper::visitVFTable(VFTableRecord &VFT) { +void CVTypeDumperImpl::visitVFTable(VFTableRecord &VFT) { printTypeIndex("CompleteClass", VFT.getCompleteClass()); printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable()); - W->printHex("VFPtrOffset", VFT.getVFPtrOffset()); - W->printString("VFTableName", VFT.getName()); + W.printHex("VFPtrOffset", VFT.getVFPtrOffset()); + W.printString("VFTableName", VFT.getName()); for (auto N : VFT.getMethodNames()) - W->printString("MethodName", N); + W.printString("MethodName", N); Name = VFT.getName(); - return Error::success(); } -Error CVTypeDumper::visitMemberFuncId(MemberFuncIdRecord &Id) { +void CVTypeDumperImpl::visitMemberFuncId(MemberFuncIdRecord &Id) { printTypeIndex("ClassType", Id.getClassType()); printTypeIndex("FunctionType", Id.getFunctionType()); - W->printString("Name", Id.getName()); + W.printString("Name", Id.getName()); Name = Id.getName(); - return Error::success(); } -Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) { +void CVTypeDumperImpl::visitProcedure(ProcedureRecord &Proc) { printTypeIndex("ReturnType", Proc.getReturnType()); - W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()), - makeArrayRef(CallingConventions)); - W->printFlags("FunctionOptions", uint8_t(Proc.getOptions()), - makeArrayRef(FunctionOptionEnum)); - W->printNumber("NumParameters", Proc.getParameterCount()); + W.printEnum("CallingConvention", uint8_t(Proc.getCallConv()), + makeArrayRef(CallingConventions)); + W.printFlags("FunctionOptions", uint8_t(Proc.getOptions()), + makeArrayRef(FunctionOptionEnum)); + W.printNumber("NumParameters", Proc.getParameterCount()); printTypeIndex("ArgListType", Proc.getArgumentList()); StringRef ReturnTypeName = getTypeName(Proc.getReturnType()); @@ -333,21 +370,20 @@ Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) { SmallString<256> TypeName(ReturnTypeName); TypeName.push_back(' '); TypeName.append(ArgListTypeName); - Name = saveName(TypeName); - return Error::success(); + Name = CVTD.saveName(TypeName); } -Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) { +void CVTypeDumperImpl::visitMemberFunction(MemberFunctionRecord &MF) { printTypeIndex("ReturnType", MF.getReturnType()); printTypeIndex("ClassType", MF.getClassType()); printTypeIndex("ThisType", MF.getThisType()); - W->printEnum("CallingConvention", uint8_t(MF.getCallConv()), - makeArrayRef(CallingConventions)); - W->printFlags("FunctionOptions", uint8_t(MF.getOptions()), - makeArrayRef(FunctionOptionEnum)); - W->printNumber("NumParameters", MF.getParameterCount()); + W.printEnum("CallingConvention", uint8_t(MF.getCallConv()), + makeArrayRef(CallingConventions)); + W.printFlags("FunctionOptions", uint8_t(MF.getOptions()), + makeArrayRef(FunctionOptionEnum)); + W.printNumber("NumParameters", MF.getParameterCount()); printTypeIndex("ArgListType", MF.getArgumentList()); - W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment()); + W.printNumber("ThisAdjustment", MF.getThisPointerAdjustment()); StringRef ReturnTypeName = getTypeName(MF.getReturnType()); StringRef ClassTypeName = getTypeName(MF.getClassType()); @@ -357,56 +393,52 @@ Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) { TypeName.append(ClassTypeName); TypeName.append("::"); TypeName.append(ArgListTypeName); - Name = saveName(TypeName); - return Error::success(); + Name = CVTD.saveName(TypeName); } -Error CVTypeDumper::visitMethodOverloadList( +void CVTypeDumperImpl::visitMethodOverloadList( MethodOverloadListRecord &MethodList) { for (auto &M : MethodList.getMethods()) { - ListScope S(*W, "Method"); + ListScope S(W, "Method"); printMemberAttributes(M.getAccess(), M.getKind(), M.getOptions()); printTypeIndex("Type", M.getType()); if (M.isIntroducingVirtual()) - W->printHex("VFTableOffset", M.getVFTableOffset()); + W.printHex("VFTableOffset", M.getVFTableOffset()); } - return Error::success(); } -Error CVTypeDumper::visitFuncId(FuncIdRecord &Func) { +void CVTypeDumperImpl::visitFuncId(FuncIdRecord &Func) { printTypeIndex("ParentScope", Func.getParentScope()); printTypeIndex("FunctionType", Func.getFunctionType()); - W->printString("Name", Func.getName()); + W.printString("Name", Func.getName()); Name = Func.getName(); - return Error::success(); } -Error CVTypeDumper::visitTypeServer2(TypeServer2Record &TS) { - W->printBinary("Signature", TS.getGuid()); - W->printNumber("Age", TS.getAge()); - W->printString("Name", TS.getName()); +void CVTypeDumperImpl::visitTypeServer2(TypeServer2Record &TS) { + W.printBinary("Signature", TS.getGuid()); + W.printNumber("Age", TS.getAge()); + W.printString("Name", TS.getName()); Name = TS.getName(); - return Error::success(); } -Error CVTypeDumper::visitPointer(PointerRecord &Ptr) { +void CVTypeDumperImpl::visitPointer(PointerRecord &Ptr) { printTypeIndex("PointeeType", Ptr.getReferentType()); - W->printHex("PointerAttributes", uint32_t(Ptr.getOptions())); - W->printEnum("PtrType", unsigned(Ptr.getPointerKind()), - makeArrayRef(PtrKindNames)); - W->printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames)); + W.printHex("PointerAttributes", uint32_t(Ptr.getOptions())); + W.printEnum("PtrType", unsigned(Ptr.getPointerKind()), + makeArrayRef(PtrKindNames)); + W.printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames)); - W->printNumber("IsFlat", Ptr.isFlat()); - W->printNumber("IsConst", Ptr.isConst()); - W->printNumber("IsVolatile", Ptr.isVolatile()); - W->printNumber("IsUnaligned", Ptr.isUnaligned()); + W.printNumber("IsFlat", Ptr.isFlat()); + W.printNumber("IsConst", Ptr.isConst()); + W.printNumber("IsVolatile", Ptr.isVolatile()); + W.printNumber("IsUnaligned", Ptr.isUnaligned()); if (Ptr.isPointerToMember()) { const MemberPointerInfo &MI = Ptr.getMemberInfo(); printTypeIndex("ClassType", MI.getContainingType()); - W->printEnum("Representation", uint16_t(MI.getRepresentation()), - makeArrayRef(PtrMemberRepNames)); + W.printEnum("Representation", uint16_t(MI.getRepresentation()), + makeArrayRef(PtrMemberRepNames)); StringRef PointeeName = getTypeName(Ptr.getReferentType()); StringRef ClassName = getTypeName(MI.getContainingType()); @@ -414,7 +446,7 @@ Error CVTypeDumper::visitPointer(PointerRecord &Ptr) { TypeName.push_back(' '); TypeName.append(ClassName); TypeName.append("::*"); - Name = saveName(TypeName); + Name = CVTD.saveName(TypeName); } else { SmallString<256> TypeName; if (Ptr.isConst()) @@ -434,15 +466,14 @@ Error CVTypeDumper::visitPointer(PointerRecord &Ptr) { TypeName.append("*"); if (!TypeName.empty()) - Name = saveName(TypeName); + Name = CVTD.saveName(TypeName); } - return Error::success(); } -Error CVTypeDumper::visitModifier(ModifierRecord &Mod) { +void CVTypeDumperImpl::visitModifier(ModifierRecord &Mod) { uint16_t Mods = static_cast(Mod.getModifiers()); printTypeIndex("ModifiedType", Mod.getModifiedType()); - W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames)); + W.printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames)); StringRef ModifiedName = getTypeName(Mod.getModifiedType()); SmallString<256> TypeName; @@ -453,162 +484,146 @@ Error CVTypeDumper::visitModifier(ModifierRecord &Mod) { if (Mods & uint16_t(ModifierOptions::Unaligned)) TypeName.append("__unaligned "); TypeName.append(ModifiedName); - Name = saveName(TypeName); - return Error::success(); + Name = CVTD.saveName(TypeName); } -Error CVTypeDumper::visitBitField(BitFieldRecord &BitField) { +void CVTypeDumperImpl::visitBitField(BitFieldRecord &BitField) { printTypeIndex("Type", BitField.getType()); - W->printNumber("BitSize", BitField.getBitSize()); - W->printNumber("BitOffset", BitField.getBitOffset()); - return Error::success(); + W.printNumber("BitSize", BitField.getBitSize()); + W.printNumber("BitOffset", BitField.getBitOffset()); } -Error CVTypeDumper::visitVFTableShape(VFTableShapeRecord &Shape) { - W->printNumber("VFEntryCount", Shape.getEntryCount()); - return Error::success(); +void CVTypeDumperImpl::visitVFTableShape(VFTableShapeRecord &Shape) { + W.printNumber("VFEntryCount", Shape.getEntryCount()); } -Error CVTypeDumper::visitUdtSourceLine(UdtSourceLineRecord &Line) { +void CVTypeDumperImpl::visitUdtSourceLine(UdtSourceLineRecord &Line) { printTypeIndex("UDT", Line.getUDT()); printTypeIndex("SourceFile", Line.getSourceFile()); - W->printNumber("LineNumber", Line.getLineNumber()); - return Error::success(); + W.printNumber("LineNumber", Line.getLineNumber()); } -Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) { +void CVTypeDumperImpl::visitUdtModSourceLine(UdtModSourceLineRecord &Line) { printTypeIndex("UDT", Line.getUDT()); printTypeIndex("SourceFile", Line.getSourceFile()); - W->printNumber("LineNumber", Line.getLineNumber()); - W->printNumber("Module", Line.getModule()); - return Error::success(); + W.printNumber("LineNumber", Line.getLineNumber()); + W.printNumber("Module", Line.getModule()); } -Error CVTypeDumper::visitBuildInfo(BuildInfoRecord &Args) { - W->printNumber("NumArgs", static_cast(Args.getArgs().size())); +void CVTypeDumperImpl::visitBuildInfo(BuildInfoRecord &Args) { + W.printNumber("NumArgs", static_cast(Args.getArgs().size())); - ListScope Arguments(*W, "Arguments"); + ListScope Arguments(W, "Arguments"); for (auto Arg : Args.getArgs()) { printTypeIndex("ArgType", Arg); } - return Error::success(); } -void CVTypeDumper::printMemberAttributes(MemberAttributes Attrs) { +void CVTypeDumperImpl::printMemberAttributes(MemberAttributes Attrs) { return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(), Attrs.getFlags()); } -void CVTypeDumper::printMemberAttributes(MemberAccess Access, MethodKind Kind, - MethodOptions Options) { - W->printEnum("AccessSpecifier", uint8_t(Access), - makeArrayRef(MemberAccessNames)); +void CVTypeDumperImpl::printMemberAttributes(MemberAccess Access, + MethodKind Kind, + MethodOptions Options) { + W.printEnum("AccessSpecifier", uint8_t(Access), + makeArrayRef(MemberAccessNames)); // Data members will be vanilla. Don't try to print a method kind for them. if (Kind != MethodKind::Vanilla) - W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames)); + W.printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames)); if (Options != MethodOptions::None) { - W->printFlags("MethodOptions", unsigned(Options), - makeArrayRef(MethodOptionNames)); + W.printFlags("MethodOptions", unsigned(Options), + makeArrayRef(MethodOptionNames)); } } -Error CVTypeDumper::visitUnknownMember(const CVRecord &Record) { - W->printHex("UnknownMember", unsigned(Record.Type)); - return Error::success(); +void CVTypeDumperImpl::visitUnknownMember(TypeLeafKind Leaf) { + W.printHex("UnknownMember", unsigned(Leaf)); } -Error CVTypeDumper::visitUnknownType(const CVRecord &Record) { - DictScope S(*W, "UnknownType"); - W->printEnum("Kind", uint16_t(Record.Type), makeArrayRef(LeafTypeNames)); - W->printNumber("Length", uint32_t(Record.Data.size())); - return Error::success(); +void CVTypeDumperImpl::visitUnknownType(const CVRecord &Rec) { + DictScope S(W, "UnknownType"); + W.printEnum("Kind", uint16_t(Rec.Type), makeArrayRef(LeafTypeNames)); + W.printNumber("Length", uint32_t(Rec.Data.size())); } -Error CVTypeDumper::visitNestedType(NestedTypeRecord &Nested) { - DictScope S(*W, "NestedType"); +void CVTypeDumperImpl::visitNestedType(NestedTypeRecord &Nested) { + DictScope S(W, "NestedType"); printTypeIndex("Type", Nested.getNestedType()); - W->printString("Name", Nested.getName()); + W.printString("Name", Nested.getName()); Name = Nested.getName(); - return Error::success(); } -Error CVTypeDumper::visitOneMethod(OneMethodRecord &Method) { - DictScope S(*W, "OneMethod"); +void CVTypeDumperImpl::visitOneMethod(OneMethodRecord &Method) { + DictScope S(W, "OneMethod"); MethodKind K = Method.getKind(); printMemberAttributes(Method.getAccess(), K, Method.getOptions()); printTypeIndex("Type", Method.getType()); // If virtual, then read the vftable offset. if (Method.isIntroducingVirtual()) - W->printHex("VFTableOffset", Method.getVFTableOffset()); - W->printString("Name", Method.getName()); + W.printHex("VFTableOffset", Method.getVFTableOffset()); + W.printString("Name", Method.getName()); Name = Method.getName(); - return Error::success(); } -Error CVTypeDumper::visitOverloadedMethod(OverloadedMethodRecord &Method) { - DictScope S(*W, "OverloadedMethod"); - W->printHex("MethodCount", Method.getNumOverloads()); +void CVTypeDumperImpl::visitOverloadedMethod(OverloadedMethodRecord &Method) { + DictScope S(W, "OverloadedMethod"); + W.printHex("MethodCount", Method.getNumOverloads()); printTypeIndex("MethodListIndex", Method.getMethodList()); - W->printString("Name", Method.getName()); + W.printString("Name", Method.getName()); Name = Method.getName(); - return Error::success(); } -Error CVTypeDumper::visitDataMember(DataMemberRecord &Field) { - DictScope S(*W, "DataMember"); +void CVTypeDumperImpl::visitDataMember(DataMemberRecord &Field) { + DictScope S(W, "DataMember"); printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, MethodOptions::None); printTypeIndex("Type", Field.getType()); - W->printHex("FieldOffset", Field.getFieldOffset()); - W->printString("Name", Field.getName()); + W.printHex("FieldOffset", Field.getFieldOffset()); + W.printString("Name", Field.getName()); Name = Field.getName(); - return Error::success(); } -Error CVTypeDumper::visitStaticDataMember(StaticDataMemberRecord &Field) { - DictScope S(*W, "StaticDataMember"); +void CVTypeDumperImpl::visitStaticDataMember(StaticDataMemberRecord &Field) { + DictScope S(W, "StaticDataMember"); printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, MethodOptions::None); printTypeIndex("Type", Field.getType()); - W->printString("Name", Field.getName()); + W.printString("Name", Field.getName()); Name = Field.getName(); - return Error::success(); } -Error CVTypeDumper::visitVFPtr(VFPtrRecord &VFTable) { - DictScope S(*W, "VFPtr"); +void CVTypeDumperImpl::visitVFPtr(VFPtrRecord &VFTable) { + DictScope S(W, "VFPtr"); printTypeIndex("Type", VFTable.getType()); - return Error::success(); } -Error CVTypeDumper::visitEnumerator(EnumeratorRecord &Enum) { - DictScope S(*W, "Enumerator"); +void CVTypeDumperImpl::visitEnumerator(EnumeratorRecord &Enum) { + DictScope S(W, "Enumerator"); printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla, MethodOptions::None); - W->printNumber("EnumValue", Enum.getValue()); - W->printString("Name", Enum.getName()); + W.printNumber("EnumValue", Enum.getValue()); + W.printString("Name", Enum.getName()); Name = Enum.getName(); - return Error::success(); } -Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) { - DictScope S(*W, "BaseClass"); +void CVTypeDumperImpl::visitBaseClass(BaseClassRecord &Base) { + DictScope S(W, "BaseClass"); printMemberAttributes(Base.getAccess(), MethodKind::Vanilla, MethodOptions::None); printTypeIndex("BaseType", Base.getBaseType()); - W->printHex("BaseOffset", Base.getBaseOffset()); - return Error::success(); + W.printHex("BaseOffset", Base.getBaseOffset()); } -Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) { - DictScope S(*W, "VirtualBaseClass"); +void CVTypeDumperImpl::visitVirtualBaseClass(VirtualBaseClassRecord &Base) { + DictScope S(W, "VirtualBaseClass"); printMemberAttributes(Base.getAccess(), MethodKind::Vanilla, MethodOptions::None); printTypeIndex("BaseType", Base.getBaseType()); printTypeIndex("VBPtrType", Base.getVBPtrType()); - W->printHex("VBPtrOffset", Base.getVBPtrOffset()); - W->printHex("VBTableIndex", Base.getVTableIndex()); - return Error::success(); + W.printHex("VBPtrOffset", Base.getVBPtrOffset()); + W.printHex("VBTableIndex", Base.getVTableIndex()); } StringRef CVTypeDumper::getTypeName(TypeIndex TI) { @@ -648,29 +663,28 @@ void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) { W->printHex(FieldName, TI.getIndex()); } -Error CVTypeDumper::dump(const CVRecord &Record) { +bool CVTypeDumper::dump(const CVRecord &Record) { assert(W && "printer should not be null"); - CVTypeVisitor Visitor(*this); - - if (auto EC = Visitor.visitTypeRecord(Record)) - return EC; - return Error::success(); + CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes); + Dumper.visitTypeRecord(Record); + return !Dumper.hadError(); } -Error CVTypeDumper::dump(const CVTypeArray &Types) { +bool CVTypeDumper::dump(const CVTypeArray &Types) { assert(W && "printer should not be null"); - CVTypeVisitor Visitor(*this); - if (auto EC = Visitor.visitTypeStream(Types)) - return EC; - return Error::success(); + CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes); + Dumper.visitTypeStream(Types); + return !Dumper.hadError(); } -Error CVTypeDumper::dump(ArrayRef Data) { +bool CVTypeDumper::dump(ArrayRef Data) { ByteStream<> Stream(Data); CVTypeArray Types; StreamReader Reader(Stream); - if (auto EC = Reader.readArray(Types, Reader.getLength())) - return EC; + if (auto EC = Reader.readArray(Types, Reader.getLength())) { + consumeError(std::move(EC)); + return false; + } return dump(Types); } diff --git a/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/lib/DebugInfo/CodeView/TypeStreamMerger.cpp index b8b035f7492..f71a31d6e38 100644 --- a/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ b/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -15,8 +15,6 @@ #include "llvm/DebugInfo/CodeView/StreamRef.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" -#include "llvm/Support/Error.h" #include "llvm/Support/ScopedPrinter.h" using namespace llvm; @@ -51,30 +49,32 @@ namespace { /// - If the type record already exists in the destination stream, discard it /// and update the type index map to forward the source type index to the /// existing destination type index. -class TypeStreamMerger : public TypeVisitorCallbacks { +class TypeStreamMerger : public CVTypeVisitor { public: TypeStreamMerger(TypeTableBuilder &DestStream) : DestStream(DestStream) { assert(!hadError()); } -/// TypeVisitorCallbacks overrides. + /// CVTypeVisitor overrides. #define TYPE_RECORD(EnumName, EnumVal, Name) \ - Error visit##Name(Name##Record &Record) override; -#define MEMBER_RECORD(EnumName, EnumVal, Name) \ - TYPE_RECORD(EnumName, EnumVal, Name) + void visit##Name(Name##Record &Record); #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + void visit##Name(Name##Record &Record); #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #include "llvm/DebugInfo/CodeView/TypeRecords.def" - Error visitUnknownType(const CVRecord &Record) override; + void visitUnknownType(const CVRecord &Record); + + void visitTypeBegin(const CVRecord &Record); + void visitTypeEnd(const CVRecord &Record); - Error visitTypeBegin(const CVRecord &Record) override; - Error visitTypeEnd(const CVRecord &Record) override; + void visitFieldList(TypeLeafKind Leaf, ArrayRef FieldData); bool mergeStream(const CVTypeArray &Types); private: - bool hadError() { return FoundBadTypeIndex; } + bool hadError() { return FoundBadTypeIndex || CVTypeVisitor::hadError(); } bool FoundBadTypeIndex = false; @@ -91,46 +91,45 @@ private: } // end anonymous namespace -Error TypeStreamMerger::visitTypeBegin(const CVRecord &Rec) { +void TypeStreamMerger::visitTypeBegin(const CVRecord &Rec) { BeginIndexMapSize = IndexMap.size(); - return Error::success(); } -Error TypeStreamMerger::visitTypeEnd(const CVRecord &Rec) { +void TypeStreamMerger::visitTypeEnd(const CVRecord &Rec) { assert(IndexMap.size() == BeginIndexMapSize + 1); - return Error::success(); +} + +void TypeStreamMerger::visitFieldList(TypeLeafKind Leaf, + ArrayRef FieldData) { + CVTypeVisitor::visitFieldList(Leaf, FieldData); + IndexMap.push_back(DestStream.writeFieldList(FieldBuilder)); + FieldBuilder.reset(); } #define TYPE_RECORD(EnumName, EnumVal, Name) \ - Error TypeStreamMerger::visit##Name(Name##Record &Record) { \ + void TypeStreamMerger::visit##Name(Name##Record &Record) { \ FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \ IndexMap.push_back(DestStream.write##Name(Record)); \ - return Error::success(); \ } #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #define MEMBER_RECORD(EnumName, EnumVal, Name) \ - Error TypeStreamMerger::visit##Name(Name##Record &Record) { \ + void TypeStreamMerger::visit##Name(Name##Record &Record) { \ FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \ FieldBuilder.write##Name(Record); \ - return Error::success(); \ } #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #include "llvm/DebugInfo/CodeView/TypeRecords.def" -Error TypeStreamMerger::visitUnknownType(const CVRecord &Rec) { +void TypeStreamMerger::visitUnknownType(const CVRecord &Rec) { // We failed to translate a type. Translate this index as "not translated". IndexMap.push_back( TypeIndex(SimpleTypeKind::NotTranslated, SimpleTypeMode::Direct)); - return llvm::make_error(cv_error_code::corrupt_record); + parseError(); } bool TypeStreamMerger::mergeStream(const CVTypeArray &Types) { assert(IndexMap.empty()); - CVTypeVisitor Visitor(*this); - if (auto EC = Visitor.visitTypeStream(Types)) { - consumeError(std::move(EC)); - return false; - } + visitTypeStream(Types); IndexMap.clear(); return !hadError(); } diff --git a/lib/DebugInfo/PDB/Raw/RawError.cpp b/lib/DebugInfo/PDB/Raw/RawError.cpp index eb169f70e11..07aebb7d739 100644 --- a/lib/DebugInfo/PDB/Raw/RawError.cpp +++ b/lib/DebugInfo/PDB/Raw/RawError.cpp @@ -32,8 +32,6 @@ public: return "The specified block address is not valid."; case raw_error_code::not_writable: return "The PDB does not support writing."; - case raw_error_code::invalid_tpi_hash: - return "The Type record has an invalid hash value."; } llvm_unreachable("Unrecognized raw_error_code"); } diff --git a/lib/DebugInfo/PDB/Raw/TpiStream.cpp b/lib/DebugInfo/PDB/Raw/TpiStream.cpp index 46717f23a63..99e5037ad63 100644 --- a/lib/DebugInfo/PDB/Raw/TpiStream.cpp +++ b/lib/DebugInfo/PDB/Raw/TpiStream.cpp @@ -84,44 +84,39 @@ template static uint32_t getTpiHash(T &Rec) { } namespace { -class TpiHashVerifier : public TypeVisitorCallbacks { +class TpiHashVerifier : public CVTypeVisitor { public: TpiHashVerifier(FixedStreamArray &HashValues, uint32_t NumHashBuckets) : HashValues(HashValues), NumHashBuckets(NumHashBuckets) {} - Error visitUdtSourceLine(UdtSourceLineRecord &Rec) override { - return verifySourceLine(Rec); - } + void visitUdtSourceLine(UdtSourceLineRecord &Rec) { verifySourceLine(Rec); } - Error visitUdtModSourceLine(UdtModSourceLineRecord &Rec) override { - return verifySourceLine(Rec); + void visitUdtModSourceLine(UdtModSourceLineRecord &Rec) { + verifySourceLine(Rec); } - Error visitClass(ClassRecord &Rec) override { return verify(Rec); } - Error visitEnum(EnumRecord &Rec) override { return verify(Rec); } - Error visitUnion(UnionRecord &Rec) override { return verify(Rec); } + void visitClass(ClassRecord &Rec) { verify(Rec); } + void visitEnum(EnumRecord &Rec) { verify(Rec); } + void visitInterface(ClassRecord &Rec) { verify(Rec); } + void visitStruct(ClassRecord &Rec) { verify(Rec); } + void visitUnion(UnionRecord &Rec) { verify(Rec); } - Error visitTypeEnd(const CVRecord &Record) override { - ++Index; - return Error::success(); - } + void visitTypeEnd(const CVRecord &Record) { ++Index; } private: - template Error verify(T &Rec) { + template void verify(T &Rec) { uint32_t Hash = getTpiHash(Rec); if (Hash && Hash % NumHashBuckets != HashValues[Index]) - return make_error(raw_error_code::invalid_tpi_hash); - return Error::success(); + parseError(); } - template Error verifySourceLine(T &Rec) { + template void verifySourceLine(T &Rec) { char Buf[4]; support::endian::write32le(Buf, Rec.getUDT().getIndex()); uint32_t Hash = hashStringV1(StringRef(Buf, 4)); if (Hash % NumHashBuckets != HashValues[Index]) - return make_error(raw_error_code::invalid_tpi_hash); - return Error::success(); + parseError(); } FixedStreamArray HashValues; @@ -134,8 +129,11 @@ private: // Currently we only verify SRC_LINE records. Error TpiStream::verifyHashValues() { TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets); - CVTypeVisitor Visitor(Verifier); - return Visitor.visitTypeStream(TypeRecords); + Verifier.visitTypeStream(TypeRecords); + if (Verifier.hadError()) + return make_error(raw_error_code::corrupt_file, + "Corrupt TPI hash table."); + return Error::success(); } Error TpiStream::reload() { diff --git a/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/tools/llvm-pdbdump/LLVMOutputStyle.cpp index 2ae63e04882..4df324f3444 100644 --- a/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ b/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -328,10 +328,8 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { for (auto &Type : Tpi->types(&HadError)) { DictScope DD(P, ""); - if (DumpRecords) { - if (auto EC = TD.dump(Type)) - return EC; - } + if (DumpRecords) + TD.dump(Type); if (DumpRecordBytes) P.printBinaryBlock("Bytes", Type.Data); @@ -349,10 +347,8 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { TD.setPrinter(nullptr); bool HadError = false; - for (auto &Type : Tpi->types(&HadError)) { - if (auto EC = TD.dump(Type)) - return EC; - } + for (auto &Type : Tpi->types(&HadError)) + TD.dump(Type); TD.setPrinter(OldP); dumpTpiHash(P, *Tpi); diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index f2efdd95839..dc7fe0e33ec 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -1108,9 +1108,9 @@ void COFFDumper::printCodeViewTypeSection(StringRef SectionName, if (Magic != COFF::DEBUG_SECTION_MAGIC) return error(object_error::parse_failed); - if (auto EC = CVTD.dump({Data.bytes_begin(), Data.bytes_end()})) { + if (!CVTD.dump({Data.bytes_begin(), Data.bytes_end()})) { W.flush(); - error(llvm::errorToErrorCode(std::move(EC))); + error(object_error::parse_failed); } }