llvm.org GIT mirror llvm / 27775cd
[codeview] Remove Type member from CVRecord Summary: Now CVType and CVSymbol are effectively type-safe wrappers around ArrayRef<uint8_t>. Make the kind() accessor load it from the RecordPrefix, which is the same for types and symbols. Reviewers: zturner, aganea Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D60018 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357658 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 4 months ago
21 changed file(s) with 73 addition(s) and 96 deletion(s). Raw diff Collapse all Expand all
2323
2424 namespace codeview {
2525
26 /// CVRecord is a fat pointer (base + size pair) to a symbol or type record.
27 /// Carrying the size separately instead of trusting the size stored in the
28 /// record prefix provides some extra safety and flexibility.
2629 template class CVRecord {
2730 public:
28 CVRecord() : Type(static_cast(0)) {}
31 CVRecord() = default;
2932
30 CVRecord(Kind K, ArrayRef Data) : Type(K), RecordData(Data) {}
33 CVRecord(ArrayRef Data) : RecordData(Data) {}
3134
32 bool valid() const { return Type != static_cast(0); }
35 CVRecord(const RecordPrefix *P, size_t Size)
36 : RecordData(reinterpret_cast(P), Size) {}
37
38 bool valid() const { return kind() != Kind(0); }
3339
3440 uint32_t length() const { return RecordData.size(); }
35 Kind kind() const { return Type; }
41
42 Kind kind() const {
43 if (RecordData.size() < sizeof(RecordPrefix))
44 return Kind(0);
45 return static_cast(static_cast(
46 reinterpret_cast(RecordData.data())->RecordKind));
47 }
48
3649 ArrayRef data() const { return RecordData; }
50
3751 StringRef str_data() const {
3852 return StringRef(reinterpret_cast(RecordData.data()),
3953 RecordData.size());
4357 return RecordData.drop_front(sizeof(RecordPrefix));
4458 }
4559
46 Kind Type;
4760 ArrayRef RecordData;
4861 };
4962
7083 ArrayRef Data = StreamBuffer.take_front(RealLen);
7184 StreamBuffer = StreamBuffer.drop_front(RealLen);
7285
73 Record R(static_cast((uint16_t)Prefix->RecordKind),
74 Data);
86 Record R(Data);
7587 if (auto EC = F(R))
7688 return EC;
7789 }
90102 return std::move(EC);
91103 if (Prefix->RecordLen < 2)
92104 return make_error(cv_error_code::corrupt_record);
93 Kind K = static_cast(uint16_t(Prefix->RecordKind));
94105
95106 Reader.setOffset(Offset);
96107 ArrayRef RawData;
97108 if (auto EC = Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t)))
98109 return std::move(EC);
99 return codeview::CVRecord(K, RawData);
110 return codeview::CVRecord(RawData);
100111 }
101112
102113 } // end namespace codeview
3030 enum : unsigned { MaxRecordLength = 0xFF00 };
3131
3232 struct RecordPrefix {
33 RecordPrefix() = default;
34 explicit RecordPrefix(uint16_t Kind) : RecordLen(2), RecordKind(Kind) {}
35
3336 ulittle16_t RecordLen; // Record length, starting from &RecordKind.
3437 ulittle16_t RecordKind; // Record kind enum (SymRecordKind or TypeRecordKind)
3538 };
5050 template
5151 static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage,
5252 CodeViewContainer Container) {
53 CVSymbol Result;
54 Result.Type = static_cast(Sym.Kind);
53 RecordPrefix Prefix{uint16_t(Sym.Kind)};
54 CVSymbol Result(&Prefix, sizeof(Prefix));
5555 SymbolSerializer Serializer(Storage, Container);
5656 consumeError(Serializer.visitSymbolBegin(Result));
5757 consumeError(Serializer.visitKnownRecord(Result, Sym));
5757 TypeRecordKind K =
5858 static_cast(uint16_t(Prefix->RecordKind));
5959 T Record(K);
60 CVType CVT(static_cast(K), Data);
60 CVType CVT(Data);
6161 if (auto EC = deserializeAs(CVT, Record))
6262 return std::move(EC);
6363 return Record;
110110
111111 public:
112112 explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) {
113 CVType FieldList;
114 FieldList.Type = TypeLeafKind::LF_FIELDLIST;
113 RecordPrefix Pre(static_cast(TypeLeafKind::LF_FIELDLIST));
114 CVType FieldList(&Pre, sizeof(Pre));
115115 consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
116116 }
117117
118118 ~FieldListDeserializer() override {
119 CVType FieldList;
120 FieldList.Type = TypeLeafKind::LF_FIELDLIST;
119 RecordPrefix Pre(static_cast(TypeLeafKind::LF_FIELDLIST));
120 CVType FieldList(&Pre, sizeof(Pre));
121121 consumeError(Mapping.Mapping.visitTypeEnd(FieldList));
122122 }
123123
4848 return Prev;
4949 }
5050
51 CVType AppendingTypeTableBuilder::getType(TypeIndex Index) {
52 CVType Type;
53 Type.RecordData = SeenRecords[Index.toArrayIndex()];
54 const RecordPrefix *P =
55 reinterpret_cast(Type.RecordData.data());
56 Type.Type = static_cast(uint16_t(P->RecordKind));
57 return Type;
51 CVType AppendingTypeTableBuilder::getType(TypeIndex Index){
52 return CVType(SeenRecords[Index.toArrayIndex()]);
5853 }
5954
6055 StringRef AppendingTypeTableBuilder::getTypeName(TypeIndex Index) {
1919 template
2020 static Error visitKnownRecord(CVSymbol &Record,
2121 SymbolVisitorCallbacks &Callbacks) {
22 SymbolRecordKind RK = static_cast(Record.Type);
22 SymbolRecordKind RK = static_cast(Record.kind());
2323 T KnownRecord(RK);
2424 if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
2525 return EC;
2828
2929 static Error finishVisitation(CVSymbol &Record,
3030 SymbolVisitorCallbacks &Callbacks) {
31 switch (Record.Type) {
31 switch (Record.kind()) {
3232 default:
3333 if (auto EC = Callbacks.visitUnknownSymbol(Record))
3434 return EC;
2121
2222 template
2323 static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
24 TypeRecordKind RK = static_cast(Record.Type);
24 TypeRecordKind RK = static_cast(Record.kind());
2525 T KnownRecord(RK);
2626 if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
2727 return EC;
9595 : Callbacks(Callbacks) {}
9696
9797 Error CVTypeVisitor::finishVisitation(CVType &Record) {
98 switch (Record.Type) {
98 switch (Record.kind()) {
9999 default:
100100 if (auto EC = Callbacks.visitUnknownType(Record))
101101 return EC;
6565 InjectedSegmentBytes =
6666 ArrayRef(FLIB, FLIB + sizeof(SegmentInjection));
6767
68 CVType Type;
69 Type.Type = getTypeLeafKind(RecordKind);
68 // Seed the first record with an appropriate record prefix.
69 RecordPrefix Prefix(getTypeLeafKind(RecordKind));
70 CVType Type(&Prefix, sizeof(Prefix));
7071 cantFail(Mapping.visitTypeBegin(Type));
7172
72 // Seed the first trecord with an appropriate record prefix.
73 RecordPrefix Prefix;
74 Prefix.RecordLen = 0;
75 Prefix.RecordKind = Type.Type;
7673 cantFail(SegmentWriter.writeObject(Prefix));
7774 }
7875
155152 MutableArrayRef Data = Buffer.data();
156153 Data = Data.slice(OffBegin, OffEnd - OffBegin);
157154
158 CVType Type;
159 Type.Type = getTypeLeafKind(*Kind);
160 Type.RecordData = Data;
161
162155 // Write the length to the RecordPrefix, making sure it does not include
163156 // sizeof(RecordPrefix.Length)
164157 RecordPrefix *Prefix = reinterpret_cast(Data.data());
165 assert(Prefix->RecordKind == Type.Type);
166158 Prefix->RecordLen = Data.size() - sizeof(RecordPrefix::RecordLen);
167159
168160 if (RefersTo.hasValue()) {
174166 CR->IndexRef = RefersTo->getIndex();
175167 }
176168
177 return Type;
169 return CVType(Data);
178170 }
179171
180172 std::vector ContinuationRecordBuilder::end(TypeIndex Index) {
181 CVType Type;
182 Type.Type = getTypeLeafKind(*Kind);
173 RecordPrefix Prefix(getTypeLeafKind(*Kind));
174 CVType Type(&Prefix, sizeof(Prefix));
183175 cantFail(Mapping.visitTypeEnd(Type));
184176
185177 // We're now done, and we have a series of segments each beginning at an
5151 }
5252
5353 CVType GlobalTypeTableBuilder::getType(TypeIndex Index) {
54 CVType Type;
55 Type.RecordData = SeenRecords[Index.toArrayIndex()];
56 if (!Type.RecordData.empty()) {
57 assert(Type.RecordData.size() >= sizeof(RecordPrefix));
58 const RecordPrefix *P =
59 reinterpret_cast(Type.RecordData.data());
60 Type.Type = static_cast(uint16_t(P->RecordKind));
61 }
54 CVType Type(SeenRecords[Index.toArrayIndex()]);
6255 return Type;
6356 }
6457
5151 }
5252
5353 CVType MergingTypeTableBuilder::getType(TypeIndex Index) {
54 CVType Type;
55 Type.RecordData = SeenRecords[Index.toArrayIndex()];
56 const RecordPrefix *P =
57 reinterpret_cast(Type.RecordData.data());
58 Type.Type = static_cast(uint16_t(P->RecordKind));
54 CVType Type(SeenRecords[Index.toArrayIndex()]);
5955 return Type;
6056 }
6157
11
22 using namespace llvm;
33 using namespace llvm::codeview;
4
5 static void writeRecordPrefix(BinaryStreamWriter &Writer, TypeLeafKind Kind) {
6 RecordPrefix Prefix;
7 Prefix.RecordKind = Kind;
8 Prefix.RecordLen = 0;
9 cantFail(Writer.writeObject(Prefix));
10 }
114
125 static void addPadding(BinaryStreamWriter &Writer) {
136 uint32_t Align = Writer.getOffset() % 4;
3124 BinaryStreamWriter Writer(ScratchBuffer, support::little);
3225 TypeRecordMapping Mapping(Writer);
3326
34 CVType CVT;
35 CVT.Type = static_cast(Record.getKind());
27 // Write the record prefix first with a dummy length but real kind.
28 RecordPrefix DummyPrefix(uint16_t(Record.getKind()));
29 cantFail(Writer.writeObject(DummyPrefix));
3630
37 writeRecordPrefix(Writer, CVT.Type);
31 RecordPrefix *Prefix = reinterpret_cast(ScratchBuffer.data());
32 CVType CVT(Prefix, sizeof(RecordPrefix));
3833
3934 cantFail(Mapping.visitTypeBegin(CVT));
4035 cantFail(Mapping.visitKnownRecord(CVT, Record));
4237
4338 addPadding(Writer);
4439
45 RecordPrefix *Prefix = reinterpret_cast(ScratchBuffer.data());
46
40 // Update the size and kind after serialization.
4741 Prefix->RecordKind = CVT.kind();
4842 Prefix->RecordLen = Writer.getOffset() - sizeof(uint16_t);
4943
100100 }
101101
102102 Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
103 W.startLine() << getSymbolKindName(CVR.Type);
103 W.startLine() << getSymbolKindName(CVR.kind());
104104 W.getOStream() << " {\n";
105105 W.indent();
106 W.printEnum("Kind", unsigned(CVR.Type), getSymbolTypeNames());
106 W.printEnum("Kind", unsigned(CVR.kind()), getSymbolTypeNames());
107107 return Error::success();
108108 }
109109
170170 }
171171
172172 Error TypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
173 W->startLine() << getLeafTypeName(Record.Type);
173 W->startLine() << getLeafTypeName(Record.kind());
174174 W->getOStream() << " (" << HexNumber(Index.getIndex()) << ")";
175175 W->getOStream() << " {\n";
176176 W->indent();
177 W->printEnum("TypeLeafKind", unsigned(Record.Type),
177 W->printEnum("TypeLeafKind", unsigned(Record.kind()),
178178 makeArrayRef(LeafTypeNames));
179179 return Error::success();
180180 }
8787 // split with continuation records. All other record types cannot be
8888 // longer than the maximum record length.
8989 Optional MaxLen;
90 if (CVR.Type != TypeLeafKind::LF_FIELDLIST &&
91 CVR.Type != TypeLeafKind::LF_METHODLIST)
90 if (CVR.kind() != TypeLeafKind::LF_FIELDLIST &&
91 CVR.kind() != TypeLeafKind::LF_METHODLIST)
9292 MaxLen = MaxRecordLength - sizeof(RecordPrefix);
9393 error(IO.beginRecord(MaxLen));
94 TypeKind = CVR.Type;
94 TypeKind = CVR.kind();
9595 return Error::success();
9696 }
9797
210210 }
211211
212212 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ClassRecord &Record) {
213 assert((CVR.Type == TypeLeafKind::LF_STRUCTURE) ||
214 (CVR.Type == TypeLeafKind::LF_CLASS) ||
215 (CVR.Type == TypeLeafKind::LF_INTERFACE));
213 assert((CVR.kind() == TypeLeafKind::LF_STRUCTURE) ||
214 (CVR.kind() == TypeLeafKind::LF_CLASS) ||
215 (CVR.kind() == TypeLeafKind::LF_INTERFACE));
216216
217217 error(IO.mapInteger(Record.MemberCount));
218218 error(IO.mapEnum(Record.Options));
3535
3636 CVType TypeTableCollection::getType(TypeIndex Index) {
3737 assert(Index.toArrayIndex() < Records.size());
38 ArrayRef Bytes = Records[Index.toArrayIndex()];
39 const RecordPrefix *Prefix =
40 reinterpret_cast(Bytes.data());
41 TypeLeafKind Kind = static_cast(uint16_t(Prefix->RecordKind));
42 return CVType(Kind, Bytes);
38 return CVType(Records[Index.toArrayIndex()]);
4339 }
4440
4541 StringRef TypeTableCollection::getTypeName(TypeIndex Index) {
3535 return Empty;
3636 }
3737 static inline CVSymbol getTombstoneKey() {
38 static CVSymbol Tombstone(static_cast(-1),
39 ArrayRef());
38 static CVSymbol Tombstone(
39 DenseMapInfo>::getTombstoneKey());
4040 return Tombstone;
4141 }
4242 static unsigned getHashValue(const CVSymbol &Val) {
247247 uint8_t *Buffer = Allocator.Allocate(TotalLen);
248248 ::memcpy(Buffer, &Prefix, sizeof(RecordPrefix));
249249 ::memcpy(Buffer + sizeof(RecordPrefix), Data.data(), Data.size());
250 return CVSymbol(Kind, ArrayRef(Buffer, TotalLen));
250 return CVSymbol(ArrayRef(Buffer, TotalLen));
251251 }
252252
253253 Error fromCodeViewSymbol(CVSymbol CVS) override {
9797
9898 CVType toCodeViewRecord(AppendingTypeTableBuilder &TS) const override {
9999 TS.writeLeafType(Record);
100 return CVType(Kind, TS.records().back());
100 return CVType(TS.records().back());
101101 }
102102
103103 mutable T Record;
495495 Member.Member->writeTo(CRB);
496496 }
497497 TS.insertRecord(CRB);
498 return CVType(Kind, TS.records().back());
498 return CVType(TS.records().back());
499499 }
500500
501501 void MappingTraits::mapping(IO &io, OneMethodRecord &Record) {
330330 // append to the existing line.
331331 P.formatLine("{0} | {1} [size = {2}]",
332332 fmt_align(Offset, AlignStyle::Right, 6),
333 formatSymbolKind(Record.Type), Record.length());
333 formatSymbolKind(Record.kind()), Record.length());
334334 P.Indent();
335335 return Error::success();
336336 }
223223 // append to the existing line.
224224 P.formatLine("{0} | {1} [size = {2}",
225225 fmt_align(Index, AlignStyle::Right, Width),
226 formatTypeLeafKind(Record.Type), Record.length());
226 formatTypeLeafKind(Record.kind()), Record.length());
227227 if (Hashes) {
228228 std::string H;
229229 if (Index.toArrayIndex() >= HashValues.size()) {
4141 }
4242
4343 inline bool operator==(const CVType &R1, const CVType &R2) {
44 if (R1.Type != R2.Type)
45 return false;
4644 if (R1.RecordData != R2.RecordData)
4745 return false;
4846 return true;
106104 GlobalState->Records.push_back(AR);
107105 GlobalState->Indices.push_back(Builder.writeLeafType(AR));
108106
109 CVType Type(TypeLeafKind::LF_ARRAY, Builder.records().back());
107 CVType Type(Builder.records().back());
110108 GlobalState->TypeVector.push_back(Type);
111109
112110 GlobalState->AllOffsets.push_back(
368366 TypeIndex IndexOne = Builder.writeLeafType(Modifier);
369367
370368 // set up a type stream that refers to the above two serialized records.
371 std::vector TypeArray;
372 TypeArray.push_back(
373 CVType(static_cast(Class.Kind), Builder.records()[0]));
374 TypeArray.push_back(
375 CVType(static_cast(Modifier.Kind), Builder.records()[1]));
369 std::vector TypeArray = {
370 {Builder.records()[0]},
371 {Builder.records()[1]},
372 };
376373 BinaryItemStream ItemStream(llvm::support::little);
377374 ItemStream.setItems(TypeArray);
378375 VarStreamArray TypeStream(ItemStream);