1b915e9e0SDimitry Andric //===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===//
2b915e9e0SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b915e9e0SDimitry Andric //
7b915e9e0SDimitry Andric //===----------------------------------------------------------------------===//
8b915e9e0SDimitry Andric
9b915e9e0SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h"
107fa27ce4SDimitry Andric #include "llvm/ADT/StringExtras.h"
11b915e9e0SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h"
12145449b1SDimitry Andric #include "llvm/DebugInfo/CodeView/GUID.h"
13b915e9e0SDimitry Andric #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
14145449b1SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeIndex.h"
1571d5a254SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
1671d5a254SDimitry Andric #include "llvm/Support/BinaryStreamWriter.h"
17b915e9e0SDimitry Andric
18b915e9e0SDimitry Andric using namespace llvm;
19b915e9e0SDimitry Andric using namespace llvm::codeview;
20b915e9e0SDimitry Andric
beginRecord(std::optional<uint32_t> MaxLength)21e3b55780SDimitry Andric Error CodeViewRecordIO::beginRecord(std::optional<uint32_t> MaxLength) {
22b915e9e0SDimitry Andric RecordLimit Limit;
23b915e9e0SDimitry Andric Limit.MaxLength = MaxLength;
24b915e9e0SDimitry Andric Limit.BeginOffset = getCurrentOffset();
25b915e9e0SDimitry Andric Limits.push_back(Limit);
26b915e9e0SDimitry Andric return Error::success();
27b915e9e0SDimitry Andric }
28b915e9e0SDimitry Andric
endRecord()29b915e9e0SDimitry Andric Error CodeViewRecordIO::endRecord() {
30b915e9e0SDimitry Andric assert(!Limits.empty() && "Not in a record!");
31b915e9e0SDimitry Andric Limits.pop_back();
32d288ef4cSDimitry Andric // We would like to assert that we actually read / wrote all the bytes that we
33d288ef4cSDimitry Andric // expected to for this record, but unfortunately we can't do this. Some
34d288ef4cSDimitry Andric // producers such as MASM over-allocate for certain types of records and
35d288ef4cSDimitry Andric // commit the extraneous data, so when reading we can't be sure every byte
36d288ef4cSDimitry Andric // will have been read. And when writing we over-allocate temporarily since
37d288ef4cSDimitry Andric // we don't know how big the record is until we're finished writing it, so
38d288ef4cSDimitry Andric // even though we don't commit the extraneous data, we still can't guarantee
39d288ef4cSDimitry Andric // we're at the end of the allocated data.
40e6d15924SDimitry Andric
41e6d15924SDimitry Andric if (isStreaming()) {
42e6d15924SDimitry Andric // For streaming mode, add padding to align with 4 byte boundaries for each
43e6d15924SDimitry Andric // record
44e6d15924SDimitry Andric uint32_t Align = getStreamedLen() % 4;
45e6d15924SDimitry Andric if (Align == 0)
46e6d15924SDimitry Andric return Error::success();
47e6d15924SDimitry Andric
48e6d15924SDimitry Andric int PaddingBytes = 4 - Align;
49e6d15924SDimitry Andric while (PaddingBytes > 0) {
50e6d15924SDimitry Andric char Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);
51e6d15924SDimitry Andric StringRef BytesSR = StringRef(&Pad, sizeof(Pad));
52cfca06d7SDimitry Andric Streamer->emitBytes(BytesSR);
53e6d15924SDimitry Andric --PaddingBytes;
54e6d15924SDimitry Andric }
551d5ae102SDimitry Andric resetStreamedLen();
56e6d15924SDimitry Andric }
57b915e9e0SDimitry Andric return Error::success();
58b915e9e0SDimitry Andric }
59b915e9e0SDimitry Andric
maxFieldLength() const60b915e9e0SDimitry Andric uint32_t CodeViewRecordIO::maxFieldLength() const {
61e6d15924SDimitry Andric if (isStreaming())
62e6d15924SDimitry Andric return 0;
63e6d15924SDimitry Andric
64b915e9e0SDimitry Andric assert(!Limits.empty() && "Not in a record!");
65b915e9e0SDimitry Andric
66b915e9e0SDimitry Andric // The max length of the next field is the minimum of all lengths that would
67b915e9e0SDimitry Andric // be allowed by any of the sub-records we're in. In practice, we can only
68b915e9e0SDimitry Andric // ever be at most 1 sub-record deep (in a FieldList), but this works for
69b915e9e0SDimitry Andric // the general case.
70b915e9e0SDimitry Andric uint32_t Offset = getCurrentOffset();
71e3b55780SDimitry Andric std::optional<uint32_t> Min = Limits.front().bytesRemaining(Offset);
72e3b55780SDimitry Andric for (auto X : ArrayRef(Limits).drop_front()) {
73e3b55780SDimitry Andric std::optional<uint32_t> ThisMin = X.bytesRemaining(Offset);
74145449b1SDimitry Andric if (ThisMin)
75145449b1SDimitry Andric Min = Min ? std::min(*Min, *ThisMin) : *ThisMin;
76b915e9e0SDimitry Andric }
77145449b1SDimitry Andric assert(Min && "Every field must have a maximum length!");
78b915e9e0SDimitry Andric
79b915e9e0SDimitry Andric return *Min;
80b915e9e0SDimitry Andric }
81b915e9e0SDimitry Andric
padToAlignment(uint32_t Align)82d288ef4cSDimitry Andric Error CodeViewRecordIO::padToAlignment(uint32_t Align) {
83d288ef4cSDimitry Andric if (isReading())
84d288ef4cSDimitry Andric return Reader->padToAlignment(Align);
85d288ef4cSDimitry Andric return Writer->padToAlignment(Align);
86d288ef4cSDimitry Andric }
87d288ef4cSDimitry Andric
skipPadding()88b915e9e0SDimitry Andric Error CodeViewRecordIO::skipPadding() {
89b915e9e0SDimitry Andric assert(!isWriting() && "Cannot skip padding while writing!");
90b915e9e0SDimitry Andric
91b915e9e0SDimitry Andric if (Reader->bytesRemaining() == 0)
92b915e9e0SDimitry Andric return Error::success();
93b915e9e0SDimitry Andric
94b915e9e0SDimitry Andric uint8_t Leaf = Reader->peek();
95b915e9e0SDimitry Andric if (Leaf < LF_PAD0)
96b915e9e0SDimitry Andric return Error::success();
97b915e9e0SDimitry Andric // Leaf is greater than 0xf0. We should advance by the number of bytes in
98b915e9e0SDimitry Andric // the low 4 bits.
99b915e9e0SDimitry Andric unsigned BytesToAdvance = Leaf & 0x0F;
100b915e9e0SDimitry Andric return Reader->skip(BytesToAdvance);
101b915e9e0SDimitry Andric }
102b915e9e0SDimitry Andric
mapByteVectorTail(ArrayRef<uint8_t> & Bytes,const Twine & Comment)103e6d15924SDimitry Andric Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes,
104e6d15924SDimitry Andric const Twine &Comment) {
105e6d15924SDimitry Andric if (isStreaming()) {
106e6d15924SDimitry Andric emitComment(Comment);
107cfca06d7SDimitry Andric Streamer->emitBinaryData(toStringRef(Bytes));
108e6d15924SDimitry Andric incrStreamedLen(Bytes.size());
109e6d15924SDimitry Andric } else if (isWriting()) {
110b915e9e0SDimitry Andric if (auto EC = Writer->writeBytes(Bytes))
111b915e9e0SDimitry Andric return EC;
112b915e9e0SDimitry Andric } else {
113b915e9e0SDimitry Andric if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining()))
114b915e9e0SDimitry Andric return EC;
115b915e9e0SDimitry Andric }
116b915e9e0SDimitry Andric return Error::success();
117b915e9e0SDimitry Andric }
118b915e9e0SDimitry Andric
mapByteVectorTail(std::vector<uint8_t> & Bytes,const Twine & Comment)119e6d15924SDimitry Andric Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes,
120e6d15924SDimitry Andric const Twine &Comment) {
121b915e9e0SDimitry Andric ArrayRef<uint8_t> BytesRef(Bytes);
122e6d15924SDimitry Andric if (auto EC = mapByteVectorTail(BytesRef, Comment))
123b915e9e0SDimitry Andric return EC;
124b915e9e0SDimitry Andric if (!isWriting())
125b915e9e0SDimitry Andric Bytes.assign(BytesRef.begin(), BytesRef.end());
126b915e9e0SDimitry Andric
127b915e9e0SDimitry Andric return Error::success();
128b915e9e0SDimitry Andric }
129b915e9e0SDimitry Andric
mapInteger(TypeIndex & TypeInd,const Twine & Comment)130e6d15924SDimitry Andric Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd, const Twine &Comment) {
131e6d15924SDimitry Andric if (isStreaming()) {
1321d5ae102SDimitry Andric std::string TypeNameStr = Streamer->getTypeName(TypeInd);
1331d5ae102SDimitry Andric if (!TypeNameStr.empty())
1341d5ae102SDimitry Andric emitComment(Comment + ": " + TypeNameStr);
1351d5ae102SDimitry Andric else
136e6d15924SDimitry Andric emitComment(Comment);
137cfca06d7SDimitry Andric Streamer->emitIntValue(TypeInd.getIndex(), sizeof(TypeInd.getIndex()));
138e6d15924SDimitry Andric incrStreamedLen(sizeof(TypeInd.getIndex()));
139e6d15924SDimitry Andric } else if (isWriting()) {
140b915e9e0SDimitry Andric if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
141b915e9e0SDimitry Andric return EC;
142e6d15924SDimitry Andric } else {
143b915e9e0SDimitry Andric uint32_t I;
144b915e9e0SDimitry Andric if (auto EC = Reader->readInteger(I))
145b915e9e0SDimitry Andric return EC;
146b915e9e0SDimitry Andric TypeInd.setIndex(I);
147e6d15924SDimitry Andric }
148b915e9e0SDimitry Andric return Error::success();
149b915e9e0SDimitry Andric }
150b915e9e0SDimitry Andric
mapEncodedInteger(int64_t & Value,const Twine & Comment)151e6d15924SDimitry Andric Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value,
152e6d15924SDimitry Andric const Twine &Comment) {
153e6d15924SDimitry Andric if (isStreaming()) {
154e6d15924SDimitry Andric if (Value >= 0)
155e6d15924SDimitry Andric emitEncodedUnsignedInteger(static_cast<uint64_t>(Value), Comment);
156e6d15924SDimitry Andric else
157e6d15924SDimitry Andric emitEncodedSignedInteger(Value, Comment);
158e6d15924SDimitry Andric } else if (isWriting()) {
159b915e9e0SDimitry Andric if (Value >= 0) {
160b915e9e0SDimitry Andric if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
161b915e9e0SDimitry Andric return EC;
162b915e9e0SDimitry Andric } else {
163b915e9e0SDimitry Andric if (auto EC = writeEncodedSignedInteger(Value))
164b915e9e0SDimitry Andric return EC;
165b915e9e0SDimitry Andric }
166b915e9e0SDimitry Andric } else {
167b915e9e0SDimitry Andric APSInt N;
168b915e9e0SDimitry Andric if (auto EC = consume(*Reader, N))
169b915e9e0SDimitry Andric return EC;
170b915e9e0SDimitry Andric Value = N.getExtValue();
171b915e9e0SDimitry Andric }
172b915e9e0SDimitry Andric
173b915e9e0SDimitry Andric return Error::success();
174b915e9e0SDimitry Andric }
175b915e9e0SDimitry Andric
mapEncodedInteger(uint64_t & Value,const Twine & Comment)176e6d15924SDimitry Andric Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value,
177e6d15924SDimitry Andric const Twine &Comment) {
178e6d15924SDimitry Andric if (isStreaming())
179e6d15924SDimitry Andric emitEncodedUnsignedInteger(Value, Comment);
180e6d15924SDimitry Andric else if (isWriting()) {
181b915e9e0SDimitry Andric if (auto EC = writeEncodedUnsignedInteger(Value))
182b915e9e0SDimitry Andric return EC;
183b915e9e0SDimitry Andric } else {
184b915e9e0SDimitry Andric APSInt N;
185b915e9e0SDimitry Andric if (auto EC = consume(*Reader, N))
186b915e9e0SDimitry Andric return EC;
187b915e9e0SDimitry Andric Value = N.getZExtValue();
188b915e9e0SDimitry Andric }
189b915e9e0SDimitry Andric return Error::success();
190b915e9e0SDimitry Andric }
191b915e9e0SDimitry Andric
mapEncodedInteger(APSInt & Value,const Twine & Comment)192e6d15924SDimitry Andric Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value, const Twine &Comment) {
193e6d15924SDimitry Andric if (isStreaming()) {
194344a3780SDimitry Andric // FIXME: We also need to handle big values here, but it's
195344a3780SDimitry Andric // not clear how we can excercise this code path yet.
196e6d15924SDimitry Andric if (Value.isSigned())
197e6d15924SDimitry Andric emitEncodedSignedInteger(Value.getSExtValue(), Comment);
198e6d15924SDimitry Andric else
199e6d15924SDimitry Andric emitEncodedUnsignedInteger(Value.getZExtValue(), Comment);
200e6d15924SDimitry Andric } else if (isWriting()) {
201b915e9e0SDimitry Andric if (Value.isSigned())
202344a3780SDimitry Andric return writeEncodedSignedInteger(
203344a3780SDimitry Andric Value.isSingleWord() ? Value.getSExtValue() : INT64_MIN);
204344a3780SDimitry Andric return writeEncodedUnsignedInteger(Value.getLimitedValue());
205e6d15924SDimitry Andric } else
206b915e9e0SDimitry Andric return consume(*Reader, Value);
207e6d15924SDimitry Andric return Error::success();
208b915e9e0SDimitry Andric }
209b915e9e0SDimitry Andric
mapStringZ(StringRef & Value,const Twine & Comment)210e6d15924SDimitry Andric Error CodeViewRecordIO::mapStringZ(StringRef &Value, const Twine &Comment) {
211e6d15924SDimitry Andric if (isStreaming()) {
212e6d15924SDimitry Andric auto NullTerminatedString = StringRef(Value.data(), Value.size() + 1);
213e6d15924SDimitry Andric emitComment(Comment);
214cfca06d7SDimitry Andric Streamer->emitBytes(NullTerminatedString);
215e6d15924SDimitry Andric incrStreamedLen(NullTerminatedString.size());
216e6d15924SDimitry Andric } else if (isWriting()) {
217b915e9e0SDimitry Andric // Truncate if we attempt to write too much.
218b915e9e0SDimitry Andric StringRef S = Value.take_front(maxFieldLength() - 1);
21971d5a254SDimitry Andric if (auto EC = Writer->writeCString(S))
220b915e9e0SDimitry Andric return EC;
221b915e9e0SDimitry Andric } else {
22271d5a254SDimitry Andric if (auto EC = Reader->readCString(Value))
223b915e9e0SDimitry Andric return EC;
224b915e9e0SDimitry Andric }
225b915e9e0SDimitry Andric return Error::success();
226b915e9e0SDimitry Andric }
227b915e9e0SDimitry Andric
mapGuid(GUID & Guid,const Twine & Comment)228e6d15924SDimitry Andric Error CodeViewRecordIO::mapGuid(GUID &Guid, const Twine &Comment) {
229b915e9e0SDimitry Andric constexpr uint32_t GuidSize = 16;
230e6d15924SDimitry Andric
231e6d15924SDimitry Andric if (isStreaming()) {
232e6d15924SDimitry Andric StringRef GuidSR =
233e6d15924SDimitry Andric StringRef((reinterpret_cast<const char *>(&Guid)), GuidSize);
234e6d15924SDimitry Andric emitComment(Comment);
235cfca06d7SDimitry Andric Streamer->emitBytes(GuidSR);
236e6d15924SDimitry Andric incrStreamedLen(GuidSize);
237e6d15924SDimitry Andric return Error::success();
238e6d15924SDimitry Andric }
239e6d15924SDimitry Andric
240b915e9e0SDimitry Andric if (maxFieldLength() < GuidSize)
241b915e9e0SDimitry Andric return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
242b915e9e0SDimitry Andric
243b915e9e0SDimitry Andric if (isWriting()) {
24493c91e39SDimitry Andric if (auto EC = Writer->writeBytes(Guid.Guid))
245b915e9e0SDimitry Andric return EC;
246b915e9e0SDimitry Andric } else {
24793c91e39SDimitry Andric ArrayRef<uint8_t> GuidBytes;
24893c91e39SDimitry Andric if (auto EC = Reader->readBytes(GuidBytes, GuidSize))
249b915e9e0SDimitry Andric return EC;
25093c91e39SDimitry Andric memcpy(Guid.Guid, GuidBytes.data(), GuidSize);
251b915e9e0SDimitry Andric }
252b915e9e0SDimitry Andric return Error::success();
253b915e9e0SDimitry Andric }
254b915e9e0SDimitry Andric
mapStringZVectorZ(std::vector<StringRef> & Value,const Twine & Comment)255e6d15924SDimitry Andric Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value,
256e6d15924SDimitry Andric const Twine &Comment) {
257e6d15924SDimitry Andric
258e6d15924SDimitry Andric if (!isReading()) {
259e6d15924SDimitry Andric emitComment(Comment);
260b915e9e0SDimitry Andric for (auto V : Value) {
261b915e9e0SDimitry Andric if (auto EC = mapStringZ(V))
262b915e9e0SDimitry Andric return EC;
263b915e9e0SDimitry Andric }
264e6d15924SDimitry Andric uint8_t FinalZero = 0;
265e6d15924SDimitry Andric if (auto EC = mapInteger(FinalZero))
266b915e9e0SDimitry Andric return EC;
267b915e9e0SDimitry Andric } else {
268b915e9e0SDimitry Andric StringRef S;
269b915e9e0SDimitry Andric if (auto EC = mapStringZ(S))
270b915e9e0SDimitry Andric return EC;
271b915e9e0SDimitry Andric while (!S.empty()) {
272b915e9e0SDimitry Andric Value.push_back(S);
273b915e9e0SDimitry Andric if (auto EC = mapStringZ(S))
274b915e9e0SDimitry Andric return EC;
275b915e9e0SDimitry Andric };
276b915e9e0SDimitry Andric }
277b915e9e0SDimitry Andric return Error::success();
278b915e9e0SDimitry Andric }
279b915e9e0SDimitry Andric
emitEncodedSignedInteger(const int64_t & Value,const Twine & Comment)280e6d15924SDimitry Andric void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value,
281e6d15924SDimitry Andric const Twine &Comment) {
282344a3780SDimitry Andric // FIXME: There are no test cases covering this function.
283344a3780SDimitry Andric // This may be because we always consider enumerators to be unsigned.
284344a3780SDimitry Andric // See FIXME at CodeViewDebug.cpp : CodeViewDebug::lowerTypeEnum.
285145449b1SDimitry Andric if (Value < LF_NUMERIC && Value >= 0) {
286145449b1SDimitry Andric emitComment(Comment);
287145449b1SDimitry Andric Streamer->emitIntValue(Value, 2);
288145449b1SDimitry Andric incrStreamedLen(2);
289145449b1SDimitry Andric } else if (Value >= std::numeric_limits<int8_t>::min() &&
290145449b1SDimitry Andric Value <= std::numeric_limits<int8_t>::max()) {
291cfca06d7SDimitry Andric Streamer->emitIntValue(LF_CHAR, 2);
292e6d15924SDimitry Andric emitComment(Comment);
293cfca06d7SDimitry Andric Streamer->emitIntValue(Value, 1);
294e6d15924SDimitry Andric incrStreamedLen(3);
295145449b1SDimitry Andric } else if (Value >= std::numeric_limits<int16_t>::min() &&
296145449b1SDimitry Andric Value <= std::numeric_limits<int16_t>::max()) {
297cfca06d7SDimitry Andric Streamer->emitIntValue(LF_SHORT, 2);
298e6d15924SDimitry Andric emitComment(Comment);
299cfca06d7SDimitry Andric Streamer->emitIntValue(Value, 2);
300e6d15924SDimitry Andric incrStreamedLen(4);
301145449b1SDimitry Andric } else if (Value >= std::numeric_limits<int32_t>::min() &&
302145449b1SDimitry Andric Value <= std::numeric_limits<int32_t>::max()) {
303cfca06d7SDimitry Andric Streamer->emitIntValue(LF_LONG, 2);
304e6d15924SDimitry Andric emitComment(Comment);
305cfca06d7SDimitry Andric Streamer->emitIntValue(Value, 4);
306e6d15924SDimitry Andric incrStreamedLen(6);
307e6d15924SDimitry Andric } else {
308cfca06d7SDimitry Andric Streamer->emitIntValue(LF_QUADWORD, 2);
309e6d15924SDimitry Andric emitComment(Comment);
310344a3780SDimitry Andric Streamer->emitIntValue(Value, 4); // FIXME: Why not 8 (size of quadword)?
311344a3780SDimitry Andric incrStreamedLen(6); // FIXME: Why not 10 (8 + 2)?
312e6d15924SDimitry Andric }
313e6d15924SDimitry Andric }
314e6d15924SDimitry Andric
emitEncodedUnsignedInteger(const uint64_t & Value,const Twine & Comment)315e6d15924SDimitry Andric void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value,
316e6d15924SDimitry Andric const Twine &Comment) {
317e6d15924SDimitry Andric if (Value < LF_NUMERIC) {
318e6d15924SDimitry Andric emitComment(Comment);
319cfca06d7SDimitry Andric Streamer->emitIntValue(Value, 2);
320e6d15924SDimitry Andric incrStreamedLen(2);
321e6d15924SDimitry Andric } else if (Value <= std::numeric_limits<uint16_t>::max()) {
322cfca06d7SDimitry Andric Streamer->emitIntValue(LF_USHORT, 2);
323e6d15924SDimitry Andric emitComment(Comment);
324cfca06d7SDimitry Andric Streamer->emitIntValue(Value, 2);
325e6d15924SDimitry Andric incrStreamedLen(4);
326e6d15924SDimitry Andric } else if (Value <= std::numeric_limits<uint32_t>::max()) {
327cfca06d7SDimitry Andric Streamer->emitIntValue(LF_ULONG, 2);
328e6d15924SDimitry Andric emitComment(Comment);
329cfca06d7SDimitry Andric Streamer->emitIntValue(Value, 4);
330e6d15924SDimitry Andric incrStreamedLen(6);
331e6d15924SDimitry Andric } else {
332344a3780SDimitry Andric // FIXME: There are no test cases covering this block.
333cfca06d7SDimitry Andric Streamer->emitIntValue(LF_UQUADWORD, 2);
334e6d15924SDimitry Andric emitComment(Comment);
335cfca06d7SDimitry Andric Streamer->emitIntValue(Value, 8);
336344a3780SDimitry Andric incrStreamedLen(6); // FIXME: Why not 10 (8 + 2)?
337e6d15924SDimitry Andric }
338e6d15924SDimitry Andric }
339e6d15924SDimitry Andric
writeEncodedSignedInteger(const int64_t & Value)340b915e9e0SDimitry Andric Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
341145449b1SDimitry Andric if (Value < LF_NUMERIC && Value >= 0) {
342145449b1SDimitry Andric if (auto EC = Writer->writeInteger<int16_t>(Value))
343145449b1SDimitry Andric return EC;
344145449b1SDimitry Andric } else if (Value >= std::numeric_limits<int8_t>::min() &&
345145449b1SDimitry Andric Value <= std::numeric_limits<int8_t>::max()) {
34671d5a254SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR))
347b915e9e0SDimitry Andric return EC;
34871d5a254SDimitry Andric if (auto EC = Writer->writeInteger<int8_t>(Value))
349b915e9e0SDimitry Andric return EC;
350145449b1SDimitry Andric } else if (Value >= std::numeric_limits<int16_t>::min() &&
351145449b1SDimitry Andric Value <= std::numeric_limits<int16_t>::max()) {
35271d5a254SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT))
353b915e9e0SDimitry Andric return EC;
35471d5a254SDimitry Andric if (auto EC = Writer->writeInteger<int16_t>(Value))
355b915e9e0SDimitry Andric return EC;
356145449b1SDimitry Andric } else if (Value >= std::numeric_limits<int32_t>::min() &&
357145449b1SDimitry Andric Value <= std::numeric_limits<int32_t>::max()) {
35871d5a254SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG))
359b915e9e0SDimitry Andric return EC;
36071d5a254SDimitry Andric if (auto EC = Writer->writeInteger<int32_t>(Value))
361b915e9e0SDimitry Andric return EC;
362b915e9e0SDimitry Andric } else {
36371d5a254SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD))
364b915e9e0SDimitry Andric return EC;
365b915e9e0SDimitry Andric if (auto EC = Writer->writeInteger(Value))
366b915e9e0SDimitry Andric return EC;
367b915e9e0SDimitry Andric }
368b915e9e0SDimitry Andric return Error::success();
369b915e9e0SDimitry Andric }
370b915e9e0SDimitry Andric
writeEncodedUnsignedInteger(const uint64_t & Value)371b915e9e0SDimitry Andric Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
372b915e9e0SDimitry Andric if (Value < LF_NUMERIC) {
37371d5a254SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(Value))
374b915e9e0SDimitry Andric return EC;
375b915e9e0SDimitry Andric } else if (Value <= std::numeric_limits<uint16_t>::max()) {
37671d5a254SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT))
377b915e9e0SDimitry Andric return EC;
37871d5a254SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(Value))
379b915e9e0SDimitry Andric return EC;
380b915e9e0SDimitry Andric } else if (Value <= std::numeric_limits<uint32_t>::max()) {
38171d5a254SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG))
382b915e9e0SDimitry Andric return EC;
38371d5a254SDimitry Andric if (auto EC = Writer->writeInteger<uint32_t>(Value))
384b915e9e0SDimitry Andric return EC;
385b915e9e0SDimitry Andric } else {
38671d5a254SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD))
387b915e9e0SDimitry Andric return EC;
388b915e9e0SDimitry Andric if (auto EC = Writer->writeInteger(Value))
389b915e9e0SDimitry Andric return EC;
390b915e9e0SDimitry Andric }
391b915e9e0SDimitry Andric
392b915e9e0SDimitry Andric return Error::success();
393b915e9e0SDimitry Andric }
394