[ARM] Split large truncating MVE stores
[llvm-complete.git] / lib / DebugInfo / CodeView / RecordSerialization.cpp
blobe7f032f9c6702f37428c77195b525c3948c1a2bd
1 //===-- RecordSerialization.cpp -------------------------------------------===//
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 //
9 // Utilities for serializing and deserializing CodeView records.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
14 #include "llvm/ADT/APInt.h"
15 #include "llvm/ADT/APSInt.h"
16 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
17 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
18 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
19 #include "llvm/Support/BinaryByteStream.h"
21 using namespace llvm;
22 using namespace llvm::codeview;
23 using namespace llvm::support;
25 /// Reinterpret a byte array as an array of characters. Does not interpret as
26 /// a C string, as StringRef has several helpers (split) that make that easy.
27 StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
28 return StringRef(reinterpret_cast<const char *>(LeafData.data()),
29 LeafData.size());
32 StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
33 return getBytesAsCharacters(LeafData).split('\0').first;
36 Error llvm::codeview::consume(BinaryStreamReader &Reader, APSInt &Num) {
37 // Used to avoid overload ambiguity on APInt construtor.
38 bool FalseVal = false;
39 uint16_t Short;
40 if (auto EC = Reader.readInteger(Short))
41 return EC;
43 if (Short < LF_NUMERIC) {
44 Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
45 /*isUnsigned=*/true);
46 return Error::success();
49 switch (Short) {
50 case LF_CHAR: {
51 int8_t N;
52 if (auto EC = Reader.readInteger(N))
53 return EC;
54 Num = APSInt(APInt(8, N, true), false);
55 return Error::success();
57 case LF_SHORT: {
58 int16_t N;
59 if (auto EC = Reader.readInteger(N))
60 return EC;
61 Num = APSInt(APInt(16, N, true), false);
62 return Error::success();
64 case LF_USHORT: {
65 uint16_t N;
66 if (auto EC = Reader.readInteger(N))
67 return EC;
68 Num = APSInt(APInt(16, N, false), true);
69 return Error::success();
71 case LF_LONG: {
72 int32_t N;
73 if (auto EC = Reader.readInteger(N))
74 return EC;
75 Num = APSInt(APInt(32, N, true), false);
76 return Error::success();
78 case LF_ULONG: {
79 uint32_t N;
80 if (auto EC = Reader.readInteger(N))
81 return EC;
82 Num = APSInt(APInt(32, N, FalseVal), true);
83 return Error::success();
85 case LF_QUADWORD: {
86 int64_t N;
87 if (auto EC = Reader.readInteger(N))
88 return EC;
89 Num = APSInt(APInt(64, N, true), false);
90 return Error::success();
92 case LF_UQUADWORD: {
93 uint64_t N;
94 if (auto EC = Reader.readInteger(N))
95 return EC;
96 Num = APSInt(APInt(64, N, false), true);
97 return Error::success();
100 return make_error<CodeViewError>(cv_error_code::corrupt_record,
101 "Buffer contains invalid APSInt type");
104 Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
105 ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
106 BinaryByteStream S(Bytes, llvm::support::little);
107 BinaryStreamReader SR(S);
108 auto EC = consume(SR, Num);
109 Data = Data.take_back(SR.bytesRemaining());
110 return EC;
113 /// Decode a numeric leaf value that is known to be a uint64_t.
114 Error llvm::codeview::consume_numeric(BinaryStreamReader &Reader,
115 uint64_t &Num) {
116 APSInt N;
117 if (auto EC = consume(Reader, N))
118 return EC;
119 if (N.isSigned() || !N.isIntN(64))
120 return make_error<CodeViewError>(cv_error_code::corrupt_record,
121 "Data is not a numeric value!");
122 Num = N.getLimitedValue();
123 return Error::success();
126 Error llvm::codeview::consume(BinaryStreamReader &Reader, uint32_t &Item) {
127 return Reader.readInteger(Item);
130 Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
131 ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
132 BinaryByteStream S(Bytes, llvm::support::little);
133 BinaryStreamReader SR(S);
134 auto EC = consume(SR, Item);
135 Data = Data.take_back(SR.bytesRemaining());
136 return EC;
139 Error llvm::codeview::consume(BinaryStreamReader &Reader, int32_t &Item) {
140 return Reader.readInteger(Item);
143 Error llvm::codeview::consume(BinaryStreamReader &Reader, StringRef &Item) {
144 if (Reader.empty())
145 return make_error<CodeViewError>(cv_error_code::corrupt_record,
146 "Null terminated string buffer is empty!");
148 return Reader.readCString(Item);
151 Expected<CVSymbol> llvm::codeview::readSymbolFromStream(BinaryStreamRef Stream,
152 uint32_t Offset) {
153 return readCVRecordFromStream<SymbolKind>(Stream, Offset);