17251ede7SZachary Turner //===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===// 27251ede7SZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 67251ede7SZachary Turner // 77251ede7SZachary Turner //===----------------------------------------------------------------------===// 87251ede7SZachary Turner 97251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h" 107251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/CodeView.h" 1181cde474Sserge-sans-paille #include "llvm/DebugInfo/CodeView/GUID.h" 127251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 1381cde474Sserge-sans-paille #include "llvm/DebugInfo/CodeView/TypeIndex.h" 14d9dc2829SZachary Turner #include "llvm/Support/BinaryStreamReader.h" 15d9dc2829SZachary Turner #include "llvm/Support/BinaryStreamWriter.h" 167251ede7SZachary Turner 177251ede7SZachary Turner using namespace llvm; 187251ede7SZachary Turner using namespace llvm::codeview; 197251ede7SZachary Turner 204efa0a42SZachary Turner Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) { 214efa0a42SZachary Turner RecordLimit Limit; 224efa0a42SZachary Turner Limit.MaxLength = MaxLength; 234efa0a42SZachary Turner Limit.BeginOffset = getCurrentOffset(); 244efa0a42SZachary Turner Limits.push_back(Limit); 257251ede7SZachary Turner return Error::success(); 267251ede7SZachary Turner } 277251ede7SZachary Turner 287251ede7SZachary Turner Error CodeViewRecordIO::endRecord() { 294efa0a42SZachary Turner assert(!Limits.empty() && "Not in a record!"); 304efa0a42SZachary Turner Limits.pop_back(); 31ebd3ae83SZachary Turner // We would like to assert that we actually read / wrote all the bytes that we 32ebd3ae83SZachary Turner // expected to for this record, but unfortunately we can't do this. Some 33ebd3ae83SZachary Turner // producers such as MASM over-allocate for certain types of records and 34ebd3ae83SZachary Turner // commit the extraneous data, so when reading we can't be sure every byte 35ebd3ae83SZachary Turner // will have been read. And when writing we over-allocate temporarily since 36ebd3ae83SZachary Turner // we don't know how big the record is until we're finished writing it, so 37ebd3ae83SZachary Turner // even though we don't commit the extraneous data, we still can't guarantee 38ebd3ae83SZachary Turner // we're at the end of the allocated data. 39faed8516SNilanjana Basu 40faed8516SNilanjana Basu if (isStreaming()) { 41faed8516SNilanjana Basu // For streaming mode, add padding to align with 4 byte boundaries for each 42faed8516SNilanjana Basu // record 43faed8516SNilanjana Basu uint32_t Align = getStreamedLen() % 4; 44faed8516SNilanjana Basu if (Align == 0) 45faed8516SNilanjana Basu return Error::success(); 46faed8516SNilanjana Basu 47faed8516SNilanjana Basu int PaddingBytes = 4 - Align; 48faed8516SNilanjana Basu while (PaddingBytes > 0) { 49faed8516SNilanjana Basu char Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes); 50faed8516SNilanjana Basu StringRef BytesSR = StringRef(&Pad, sizeof(Pad)); 51a55daa14SFangrui Song Streamer->emitBytes(BytesSR); 52faed8516SNilanjana Basu --PaddingBytes; 53faed8516SNilanjana Basu } 5406b8fe8dSNilanjana Basu resetStreamedLen(); 55faed8516SNilanjana Basu } 567251ede7SZachary Turner return Error::success(); 577251ede7SZachary Turner } 587251ede7SZachary Turner 594efa0a42SZachary Turner uint32_t CodeViewRecordIO::maxFieldLength() const { 60faed8516SNilanjana Basu if (isStreaming()) 61faed8516SNilanjana Basu return 0; 62faed8516SNilanjana Basu 634efa0a42SZachary Turner assert(!Limits.empty() && "Not in a record!"); 644efa0a42SZachary Turner 654efa0a42SZachary Turner // The max length of the next field is the minimum of all lengths that would 664efa0a42SZachary Turner // be allowed by any of the sub-records we're in. In practice, we can only 674efa0a42SZachary Turner // ever be at most 1 sub-record deep (in a FieldList), but this works for 684efa0a42SZachary Turner // the general case. 694efa0a42SZachary Turner uint32_t Offset = getCurrentOffset(); 704efa0a42SZachary Turner Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset); 714efa0a42SZachary Turner for (auto X : makeArrayRef(Limits).drop_front()) { 724efa0a42SZachary Turner Optional<uint32_t> ThisMin = X.bytesRemaining(Offset); 734efa0a42SZachary Turner if (ThisMin.hasValue()) 744efa0a42SZachary Turner Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin; 754efa0a42SZachary Turner } 764efa0a42SZachary Turner assert(Min.hasValue() && "Every field must have a maximum length!"); 774efa0a42SZachary Turner 784efa0a42SZachary Turner return *Min; 794efa0a42SZachary Turner } 804efa0a42SZachary Turner 81ebd3ae83SZachary Turner Error CodeViewRecordIO::padToAlignment(uint32_t Align) { 82ebd3ae83SZachary Turner if (isReading()) 83ebd3ae83SZachary Turner return Reader->padToAlignment(Align); 84ebd3ae83SZachary Turner return Writer->padToAlignment(Align); 85ebd3ae83SZachary Turner } 86ebd3ae83SZachary Turner 877251ede7SZachary Turner Error CodeViewRecordIO::skipPadding() { 887251ede7SZachary Turner assert(!isWriting() && "Cannot skip padding while writing!"); 897251ede7SZachary Turner 907251ede7SZachary Turner if (Reader->bytesRemaining() == 0) 917251ede7SZachary Turner return Error::success(); 927251ede7SZachary Turner 937251ede7SZachary Turner uint8_t Leaf = Reader->peek(); 947251ede7SZachary Turner if (Leaf < LF_PAD0) 957251ede7SZachary Turner return Error::success(); 967251ede7SZachary Turner // Leaf is greater than 0xf0. We should advance by the number of bytes in 977251ede7SZachary Turner // the low 4 bits. 987251ede7SZachary Turner unsigned BytesToAdvance = Leaf & 0x0F; 997251ede7SZachary Turner return Reader->skip(BytesToAdvance); 1007251ede7SZachary Turner } 1017251ede7SZachary Turner 1026e407669SNilanjana Basu Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes, 1036e407669SNilanjana Basu const Twine &Comment) { 104faed8516SNilanjana Basu if (isStreaming()) { 1056e407669SNilanjana Basu emitComment(Comment); 106a55daa14SFangrui Song Streamer->emitBinaryData(toStringRef(Bytes)); 107faed8516SNilanjana Basu incrStreamedLen(Bytes.size()); 108faed8516SNilanjana Basu } else if (isWriting()) { 1097251ede7SZachary Turner if (auto EC = Writer->writeBytes(Bytes)) 1107251ede7SZachary Turner return EC; 1117251ede7SZachary Turner } else { 1127251ede7SZachary Turner if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining())) 1137251ede7SZachary Turner return EC; 1147251ede7SZachary Turner } 1157251ede7SZachary Turner return Error::success(); 1167251ede7SZachary Turner } 1177251ede7SZachary Turner 1186e407669SNilanjana Basu Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes, 1196e407669SNilanjana Basu const Twine &Comment) { 12046225b19SZachary Turner ArrayRef<uint8_t> BytesRef(Bytes); 1216e407669SNilanjana Basu if (auto EC = mapByteVectorTail(BytesRef, Comment)) 12246225b19SZachary Turner return EC; 12346225b19SZachary Turner if (!isWriting()) 12446225b19SZachary Turner Bytes.assign(BytesRef.begin(), BytesRef.end()); 12546225b19SZachary Turner 12646225b19SZachary Turner return Error::success(); 12746225b19SZachary Turner } 12846225b19SZachary Turner 1296e407669SNilanjana Basu Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd, const Twine &Comment) { 130faed8516SNilanjana Basu if (isStreaming()) { 131ac3851c4SNilanjana Basu std::string TypeNameStr = Streamer->getTypeName(TypeInd); 132ac3851c4SNilanjana Basu if (!TypeNameStr.empty()) 133ac3851c4SNilanjana Basu emitComment(Comment + ": " + TypeNameStr); 134ac3851c4SNilanjana Basu else 1356e407669SNilanjana Basu emitComment(Comment); 13677497103SFangrui Song Streamer->emitIntValue(TypeInd.getIndex(), sizeof(TypeInd.getIndex())); 137faed8516SNilanjana Basu incrStreamedLen(sizeof(TypeInd.getIndex())); 138faed8516SNilanjana Basu } else if (isWriting()) { 139695ed56bSZachary Turner if (auto EC = Writer->writeInteger(TypeInd.getIndex())) 1407251ede7SZachary Turner return EC; 141faed8516SNilanjana Basu } else { 1427251ede7SZachary Turner uint32_t I; 143695ed56bSZachary Turner if (auto EC = Reader->readInteger(I)) 1447251ede7SZachary Turner return EC; 1457251ede7SZachary Turner TypeInd.setIndex(I); 146faed8516SNilanjana Basu } 1477251ede7SZachary Turner return Error::success(); 1487251ede7SZachary Turner } 1497251ede7SZachary Turner 1506e407669SNilanjana Basu Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value, 1516e407669SNilanjana Basu const Twine &Comment) { 152faed8516SNilanjana Basu if (isStreaming()) { 153faed8516SNilanjana Basu if (Value >= 0) 1546e407669SNilanjana Basu emitEncodedUnsignedInteger(static_cast<uint64_t>(Value), Comment); 155faed8516SNilanjana Basu else 1566e407669SNilanjana Basu emitEncodedSignedInteger(Value, Comment); 157faed8516SNilanjana Basu } else if (isWriting()) { 1587251ede7SZachary Turner if (Value >= 0) { 1597251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value))) 1607251ede7SZachary Turner return EC; 1617251ede7SZachary Turner } else { 1627251ede7SZachary Turner if (auto EC = writeEncodedSignedInteger(Value)) 1637251ede7SZachary Turner return EC; 1647251ede7SZachary Turner } 1657251ede7SZachary Turner } else { 1667251ede7SZachary Turner APSInt N; 1677251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1687251ede7SZachary Turner return EC; 1697251ede7SZachary Turner Value = N.getExtValue(); 1707251ede7SZachary Turner } 1717251ede7SZachary Turner 1727251ede7SZachary Turner return Error::success(); 1737251ede7SZachary Turner } 1747251ede7SZachary Turner 1756e407669SNilanjana Basu Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value, 1766e407669SNilanjana Basu const Twine &Comment) { 177faed8516SNilanjana Basu if (isStreaming()) 1786e407669SNilanjana Basu emitEncodedUnsignedInteger(Value, Comment); 179faed8516SNilanjana Basu else if (isWriting()) { 1807251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(Value)) 1817251ede7SZachary Turner return EC; 1827251ede7SZachary Turner } else { 1837251ede7SZachary Turner APSInt N; 1847251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1857251ede7SZachary Turner return EC; 1867251ede7SZachary Turner Value = N.getZExtValue(); 1877251ede7SZachary Turner } 1887251ede7SZachary Turner return Error::success(); 1897251ede7SZachary Turner } 1907251ede7SZachary Turner 1916e407669SNilanjana Basu Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value, const Twine &Comment) { 192faed8516SNilanjana Basu if (isStreaming()) { 193f84c70a3SMatheus Izvekov // FIXME: We also need to handle big values here, but it's 194f84c70a3SMatheus Izvekov // not clear how we can excercise this code path yet. 195faed8516SNilanjana Basu if (Value.isSigned()) 1966e407669SNilanjana Basu emitEncodedSignedInteger(Value.getSExtValue(), Comment); 197faed8516SNilanjana Basu else 1986e407669SNilanjana Basu emitEncodedUnsignedInteger(Value.getZExtValue(), Comment); 199faed8516SNilanjana Basu } else if (isWriting()) { 2007251ede7SZachary Turner if (Value.isSigned()) 201f84c70a3SMatheus Izvekov return writeEncodedSignedInteger( 202f84c70a3SMatheus Izvekov Value.isSingleWord() ? Value.getSExtValue() : INT64_MIN); 203f84c70a3SMatheus Izvekov return writeEncodedUnsignedInteger(Value.getLimitedValue()); 204faed8516SNilanjana Basu } else 2057251ede7SZachary Turner return consume(*Reader, Value); 206faed8516SNilanjana Basu return Error::success(); 2077251ede7SZachary Turner } 2087251ede7SZachary Turner 2096e407669SNilanjana Basu Error CodeViewRecordIO::mapStringZ(StringRef &Value, const Twine &Comment) { 210faed8516SNilanjana Basu if (isStreaming()) { 211faed8516SNilanjana Basu auto NullTerminatedString = StringRef(Value.data(), Value.size() + 1); 2126e407669SNilanjana Basu emitComment(Comment); 213a55daa14SFangrui Song Streamer->emitBytes(NullTerminatedString); 214faed8516SNilanjana Basu incrStreamedLen(NullTerminatedString.size()); 215faed8516SNilanjana Basu } else if (isWriting()) { 2164efa0a42SZachary Turner // Truncate if we attempt to write too much. 2174efa0a42SZachary Turner StringRef S = Value.take_front(maxFieldLength() - 1); 218120faca4SZachary Turner if (auto EC = Writer->writeCString(S)) 2197251ede7SZachary Turner return EC; 2207251ede7SZachary Turner } else { 221120faca4SZachary Turner if (auto EC = Reader->readCString(Value)) 2227251ede7SZachary Turner return EC; 2237251ede7SZachary Turner } 2247251ede7SZachary Turner return Error::success(); 2257251ede7SZachary Turner } 2267251ede7SZachary Turner 2276e407669SNilanjana Basu Error CodeViewRecordIO::mapGuid(GUID &Guid, const Twine &Comment) { 2284efa0a42SZachary Turner constexpr uint32_t GuidSize = 16; 229faed8516SNilanjana Basu 230faed8516SNilanjana Basu if (isStreaming()) { 231faed8516SNilanjana Basu StringRef GuidSR = 232faed8516SNilanjana Basu StringRef((reinterpret_cast<const char *>(&Guid)), GuidSize); 2336e407669SNilanjana Basu emitComment(Comment); 234a55daa14SFangrui Song Streamer->emitBytes(GuidSR); 235faed8516SNilanjana Basu incrStreamedLen(GuidSize); 236faed8516SNilanjana Basu return Error::success(); 237faed8516SNilanjana Basu } 238faed8516SNilanjana Basu 2394efa0a42SZachary Turner if (maxFieldLength() < GuidSize) 2404efa0a42SZachary Turner return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 2414efa0a42SZachary Turner 2427251ede7SZachary Turner if (isWriting()) { 24367653ee0SReid Kleckner if (auto EC = Writer->writeBytes(Guid.Guid)) 2447251ede7SZachary Turner return EC; 2457251ede7SZachary Turner } else { 24667653ee0SReid Kleckner ArrayRef<uint8_t> GuidBytes; 24767653ee0SReid Kleckner if (auto EC = Reader->readBytes(GuidBytes, GuidSize)) 2487251ede7SZachary Turner return EC; 24967653ee0SReid Kleckner memcpy(Guid.Guid, GuidBytes.data(), GuidSize); 2507251ede7SZachary Turner } 2517251ede7SZachary Turner return Error::success(); 2527251ede7SZachary Turner } 2537251ede7SZachary Turner 2546e407669SNilanjana Basu Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value, 2556e407669SNilanjana Basu const Twine &Comment) { 256faed8516SNilanjana Basu 257faed8516SNilanjana Basu if (!isReading()) { 2586e407669SNilanjana Basu emitComment(Comment); 25946225b19SZachary Turner for (auto V : Value) { 26046225b19SZachary Turner if (auto EC = mapStringZ(V)) 26146225b19SZachary Turner return EC; 26246225b19SZachary Turner } 263faed8516SNilanjana Basu uint8_t FinalZero = 0; 264faed8516SNilanjana Basu if (auto EC = mapInteger(FinalZero)) 26546225b19SZachary Turner return EC; 26646225b19SZachary Turner } else { 26746225b19SZachary Turner StringRef S; 26846225b19SZachary Turner if (auto EC = mapStringZ(S)) 26946225b19SZachary Turner return EC; 27046225b19SZachary Turner while (!S.empty()) { 27146225b19SZachary Turner Value.push_back(S); 27246225b19SZachary Turner if (auto EC = mapStringZ(S)) 27346225b19SZachary Turner return EC; 27446225b19SZachary Turner }; 27546225b19SZachary Turner } 27646225b19SZachary Turner return Error::success(); 27746225b19SZachary Turner } 27846225b19SZachary Turner 2796e407669SNilanjana Basu void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value, 2806e407669SNilanjana Basu const Twine &Comment) { 281f84c70a3SMatheus Izvekov // FIXME: There are no test cases covering this function. 282f84c70a3SMatheus Izvekov // This may be because we always consider enumerators to be unsigned. 283f84c70a3SMatheus Izvekov // See FIXME at CodeViewDebug.cpp : CodeViewDebug::lowerTypeEnum. 284*fe9923f2SSteve Merritt if (Value < LF_NUMERIC && Value >= 0) { 285*fe9923f2SSteve Merritt emitComment(Comment); 286*fe9923f2SSteve Merritt Streamer->emitIntValue(Value, 2); 287*fe9923f2SSteve Merritt incrStreamedLen(2); 288*fe9923f2SSteve Merritt } else if (Value >= std::numeric_limits<int8_t>::min() && 289*fe9923f2SSteve Merritt Value <= std::numeric_limits<int8_t>::max()) { 29077497103SFangrui Song Streamer->emitIntValue(LF_CHAR, 2); 2916e407669SNilanjana Basu emitComment(Comment); 29277497103SFangrui Song Streamer->emitIntValue(Value, 1); 293faed8516SNilanjana Basu incrStreamedLen(3); 294*fe9923f2SSteve Merritt } else if (Value >= std::numeric_limits<int16_t>::min() && 295*fe9923f2SSteve Merritt Value <= std::numeric_limits<int16_t>::max()) { 29677497103SFangrui Song Streamer->emitIntValue(LF_SHORT, 2); 2976e407669SNilanjana Basu emitComment(Comment); 29877497103SFangrui Song Streamer->emitIntValue(Value, 2); 299faed8516SNilanjana Basu incrStreamedLen(4); 300*fe9923f2SSteve Merritt } else if (Value >= std::numeric_limits<int32_t>::min() && 301*fe9923f2SSteve Merritt Value <= std::numeric_limits<int32_t>::max()) { 30277497103SFangrui Song Streamer->emitIntValue(LF_LONG, 2); 3036e407669SNilanjana Basu emitComment(Comment); 30477497103SFangrui Song Streamer->emitIntValue(Value, 4); 305faed8516SNilanjana Basu incrStreamedLen(6); 306faed8516SNilanjana Basu } else { 30777497103SFangrui Song Streamer->emitIntValue(LF_QUADWORD, 2); 3086e407669SNilanjana Basu emitComment(Comment); 309f84c70a3SMatheus Izvekov Streamer->emitIntValue(Value, 4); // FIXME: Why not 8 (size of quadword)? 310f84c70a3SMatheus Izvekov incrStreamedLen(6); // FIXME: Why not 10 (8 + 2)? 311faed8516SNilanjana Basu } 312faed8516SNilanjana Basu } 313faed8516SNilanjana Basu 3146e407669SNilanjana Basu void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value, 3156e407669SNilanjana Basu const Twine &Comment) { 316faed8516SNilanjana Basu if (Value < LF_NUMERIC) { 3176e407669SNilanjana Basu emitComment(Comment); 31877497103SFangrui Song Streamer->emitIntValue(Value, 2); 319faed8516SNilanjana Basu incrStreamedLen(2); 320faed8516SNilanjana Basu } else if (Value <= std::numeric_limits<uint16_t>::max()) { 32177497103SFangrui Song Streamer->emitIntValue(LF_USHORT, 2); 3226e407669SNilanjana Basu emitComment(Comment); 32377497103SFangrui Song Streamer->emitIntValue(Value, 2); 324faed8516SNilanjana Basu incrStreamedLen(4); 325faed8516SNilanjana Basu } else if (Value <= std::numeric_limits<uint32_t>::max()) { 32677497103SFangrui Song Streamer->emitIntValue(LF_ULONG, 2); 3276e407669SNilanjana Basu emitComment(Comment); 32877497103SFangrui Song Streamer->emitIntValue(Value, 4); 329faed8516SNilanjana Basu incrStreamedLen(6); 330faed8516SNilanjana Basu } else { 331f84c70a3SMatheus Izvekov // FIXME: There are no test cases covering this block. 33277497103SFangrui Song Streamer->emitIntValue(LF_UQUADWORD, 2); 3336e407669SNilanjana Basu emitComment(Comment); 33477497103SFangrui Song Streamer->emitIntValue(Value, 8); 335f84c70a3SMatheus Izvekov incrStreamedLen(6); // FIXME: Why not 10 (8 + 2)? 336faed8516SNilanjana Basu } 337faed8516SNilanjana Basu } 338faed8516SNilanjana Basu 3397251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { 340*fe9923f2SSteve Merritt if (Value < LF_NUMERIC && Value >= 0) { 341*fe9923f2SSteve Merritt if (auto EC = Writer->writeInteger<int16_t>(Value)) 342*fe9923f2SSteve Merritt return EC; 343*fe9923f2SSteve Merritt } else if (Value >= std::numeric_limits<int8_t>::min() && 344*fe9923f2SSteve Merritt Value <= std::numeric_limits<int8_t>::max()) { 345695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR)) 3467251ede7SZachary Turner return EC; 347695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int8_t>(Value)) 3487251ede7SZachary Turner return EC; 349*fe9923f2SSteve Merritt } else if (Value >= std::numeric_limits<int16_t>::min() && 350*fe9923f2SSteve Merritt Value <= std::numeric_limits<int16_t>::max()) { 351695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT)) 3527251ede7SZachary Turner return EC; 353695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int16_t>(Value)) 3547251ede7SZachary Turner return EC; 355*fe9923f2SSteve Merritt } else if (Value >= std::numeric_limits<int32_t>::min() && 356*fe9923f2SSteve Merritt Value <= std::numeric_limits<int32_t>::max()) { 357695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG)) 3587251ede7SZachary Turner return EC; 359695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int32_t>(Value)) 3607251ede7SZachary Turner return EC; 3617251ede7SZachary Turner } else { 362695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD)) 3637251ede7SZachary Turner return EC; 364695ed56bSZachary Turner if (auto EC = Writer->writeInteger(Value)) 3657251ede7SZachary Turner return EC; 3667251ede7SZachary Turner } 3677251ede7SZachary Turner return Error::success(); 3687251ede7SZachary Turner } 3697251ede7SZachary Turner 3707251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) { 3717251ede7SZachary Turner if (Value < LF_NUMERIC) { 372695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(Value)) 3737251ede7SZachary Turner return EC; 3747251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint16_t>::max()) { 375695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT)) 3767251ede7SZachary Turner return EC; 377695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(Value)) 3787251ede7SZachary Turner return EC; 3797251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint32_t>::max()) { 380695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG)) 3817251ede7SZachary Turner return EC; 382695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint32_t>(Value)) 3837251ede7SZachary Turner return EC; 3847251ede7SZachary Turner } else { 385695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD)) 3867251ede7SZachary Turner return EC; 387695ed56bSZachary Turner if (auto EC = Writer->writeInteger(Value)) 3887251ede7SZachary Turner return EC; 3897251ede7SZachary Turner } 3907251ede7SZachary Turner 3917251ede7SZachary Turner return Error::success(); 3927251ede7SZachary Turner } 393