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" 117251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 12d9dc2829SZachary Turner #include "llvm/Support/BinaryStreamReader.h" 13d9dc2829SZachary Turner #include "llvm/Support/BinaryStreamWriter.h" 147251ede7SZachary Turner 157251ede7SZachary Turner using namespace llvm; 167251ede7SZachary Turner using namespace llvm::codeview; 177251ede7SZachary Turner 184efa0a42SZachary Turner Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) { 194efa0a42SZachary Turner RecordLimit Limit; 204efa0a42SZachary Turner Limit.MaxLength = MaxLength; 214efa0a42SZachary Turner Limit.BeginOffset = getCurrentOffset(); 224efa0a42SZachary Turner Limits.push_back(Limit); 237251ede7SZachary Turner return Error::success(); 247251ede7SZachary Turner } 257251ede7SZachary Turner 267251ede7SZachary Turner Error CodeViewRecordIO::endRecord() { 274efa0a42SZachary Turner assert(!Limits.empty() && "Not in a record!"); 284efa0a42SZachary Turner Limits.pop_back(); 29ebd3ae83SZachary Turner // We would like to assert that we actually read / wrote all the bytes that we 30ebd3ae83SZachary Turner // expected to for this record, but unfortunately we can't do this. Some 31ebd3ae83SZachary Turner // producers such as MASM over-allocate for certain types of records and 32ebd3ae83SZachary Turner // commit the extraneous data, so when reading we can't be sure every byte 33ebd3ae83SZachary Turner // will have been read. And when writing we over-allocate temporarily since 34ebd3ae83SZachary Turner // we don't know how big the record is until we're finished writing it, so 35ebd3ae83SZachary Turner // even though we don't commit the extraneous data, we still can't guarantee 36ebd3ae83SZachary Turner // we're at the end of the allocated data. 37faed8516SNilanjana Basu 38faed8516SNilanjana Basu if (isStreaming()) { 39faed8516SNilanjana Basu // For streaming mode, add padding to align with 4 byte boundaries for each 40faed8516SNilanjana Basu // record 41faed8516SNilanjana Basu uint32_t Align = getStreamedLen() % 4; 42faed8516SNilanjana Basu if (Align == 0) 43faed8516SNilanjana Basu return Error::success(); 44faed8516SNilanjana Basu 45faed8516SNilanjana Basu int PaddingBytes = 4 - Align; 46faed8516SNilanjana Basu while (PaddingBytes > 0) { 47faed8516SNilanjana Basu char Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes); 48faed8516SNilanjana Basu StringRef BytesSR = StringRef(&Pad, sizeof(Pad)); 49*a55daa14SFangrui Song Streamer->emitBytes(BytesSR); 50faed8516SNilanjana Basu --PaddingBytes; 51faed8516SNilanjana Basu } 5206b8fe8dSNilanjana Basu resetStreamedLen(); 53faed8516SNilanjana Basu } 547251ede7SZachary Turner return Error::success(); 557251ede7SZachary Turner } 567251ede7SZachary Turner 574efa0a42SZachary Turner uint32_t CodeViewRecordIO::maxFieldLength() const { 58faed8516SNilanjana Basu if (isStreaming()) 59faed8516SNilanjana Basu return 0; 60faed8516SNilanjana Basu 614efa0a42SZachary Turner assert(!Limits.empty() && "Not in a record!"); 624efa0a42SZachary Turner 634efa0a42SZachary Turner // The max length of the next field is the minimum of all lengths that would 644efa0a42SZachary Turner // be allowed by any of the sub-records we're in. In practice, we can only 654efa0a42SZachary Turner // ever be at most 1 sub-record deep (in a FieldList), but this works for 664efa0a42SZachary Turner // the general case. 674efa0a42SZachary Turner uint32_t Offset = getCurrentOffset(); 684efa0a42SZachary Turner Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset); 694efa0a42SZachary Turner for (auto X : makeArrayRef(Limits).drop_front()) { 704efa0a42SZachary Turner Optional<uint32_t> ThisMin = X.bytesRemaining(Offset); 714efa0a42SZachary Turner if (ThisMin.hasValue()) 724efa0a42SZachary Turner Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin; 734efa0a42SZachary Turner } 744efa0a42SZachary Turner assert(Min.hasValue() && "Every field must have a maximum length!"); 754efa0a42SZachary Turner 764efa0a42SZachary Turner return *Min; 774efa0a42SZachary Turner } 784efa0a42SZachary Turner 79ebd3ae83SZachary Turner Error CodeViewRecordIO::padToAlignment(uint32_t Align) { 80ebd3ae83SZachary Turner if (isReading()) 81ebd3ae83SZachary Turner return Reader->padToAlignment(Align); 82ebd3ae83SZachary Turner return Writer->padToAlignment(Align); 83ebd3ae83SZachary Turner } 84ebd3ae83SZachary Turner 857251ede7SZachary Turner Error CodeViewRecordIO::skipPadding() { 867251ede7SZachary Turner assert(!isWriting() && "Cannot skip padding while writing!"); 877251ede7SZachary Turner 887251ede7SZachary Turner if (Reader->bytesRemaining() == 0) 897251ede7SZachary Turner return Error::success(); 907251ede7SZachary Turner 917251ede7SZachary Turner uint8_t Leaf = Reader->peek(); 927251ede7SZachary Turner if (Leaf < LF_PAD0) 937251ede7SZachary Turner return Error::success(); 947251ede7SZachary Turner // Leaf is greater than 0xf0. We should advance by the number of bytes in 957251ede7SZachary Turner // the low 4 bits. 967251ede7SZachary Turner unsigned BytesToAdvance = Leaf & 0x0F; 977251ede7SZachary Turner return Reader->skip(BytesToAdvance); 987251ede7SZachary Turner } 997251ede7SZachary Turner 1006e407669SNilanjana Basu Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes, 1016e407669SNilanjana Basu const Twine &Comment) { 102faed8516SNilanjana Basu if (isStreaming()) { 1036e407669SNilanjana Basu emitComment(Comment); 104*a55daa14SFangrui Song Streamer->emitBinaryData(toStringRef(Bytes)); 105faed8516SNilanjana Basu incrStreamedLen(Bytes.size()); 106faed8516SNilanjana Basu } else if (isWriting()) { 1077251ede7SZachary Turner if (auto EC = Writer->writeBytes(Bytes)) 1087251ede7SZachary Turner return EC; 1097251ede7SZachary Turner } else { 1107251ede7SZachary Turner if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining())) 1117251ede7SZachary Turner return EC; 1127251ede7SZachary Turner } 1137251ede7SZachary Turner return Error::success(); 1147251ede7SZachary Turner } 1157251ede7SZachary Turner 1166e407669SNilanjana Basu Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes, 1176e407669SNilanjana Basu const Twine &Comment) { 11846225b19SZachary Turner ArrayRef<uint8_t> BytesRef(Bytes); 1196e407669SNilanjana Basu if (auto EC = mapByteVectorTail(BytesRef, Comment)) 12046225b19SZachary Turner return EC; 12146225b19SZachary Turner if (!isWriting()) 12246225b19SZachary Turner Bytes.assign(BytesRef.begin(), BytesRef.end()); 12346225b19SZachary Turner 12446225b19SZachary Turner return Error::success(); 12546225b19SZachary Turner } 12646225b19SZachary Turner 1276e407669SNilanjana Basu Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd, const Twine &Comment) { 128faed8516SNilanjana Basu if (isStreaming()) { 129ac3851c4SNilanjana Basu std::string TypeNameStr = Streamer->getTypeName(TypeInd); 130ac3851c4SNilanjana Basu if (!TypeNameStr.empty()) 131ac3851c4SNilanjana Basu emitComment(Comment + ": " + TypeNameStr); 132ac3851c4SNilanjana Basu else 1336e407669SNilanjana Basu emitComment(Comment); 134faed8516SNilanjana Basu Streamer->EmitIntValue(TypeInd.getIndex(), sizeof(TypeInd.getIndex())); 135faed8516SNilanjana Basu incrStreamedLen(sizeof(TypeInd.getIndex())); 136faed8516SNilanjana Basu } else if (isWriting()) { 137695ed56bSZachary Turner if (auto EC = Writer->writeInteger(TypeInd.getIndex())) 1387251ede7SZachary Turner return EC; 139faed8516SNilanjana Basu } else { 1407251ede7SZachary Turner uint32_t I; 141695ed56bSZachary Turner if (auto EC = Reader->readInteger(I)) 1427251ede7SZachary Turner return EC; 1437251ede7SZachary Turner TypeInd.setIndex(I); 144faed8516SNilanjana Basu } 1457251ede7SZachary Turner return Error::success(); 1467251ede7SZachary Turner } 1477251ede7SZachary Turner 1486e407669SNilanjana Basu Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value, 1496e407669SNilanjana Basu const Twine &Comment) { 150faed8516SNilanjana Basu if (isStreaming()) { 151faed8516SNilanjana Basu if (Value >= 0) 1526e407669SNilanjana Basu emitEncodedUnsignedInteger(static_cast<uint64_t>(Value), Comment); 153faed8516SNilanjana Basu else 1546e407669SNilanjana Basu emitEncodedSignedInteger(Value, Comment); 155faed8516SNilanjana Basu } else if (isWriting()) { 1567251ede7SZachary Turner if (Value >= 0) { 1577251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value))) 1587251ede7SZachary Turner return EC; 1597251ede7SZachary Turner } else { 1607251ede7SZachary Turner if (auto EC = writeEncodedSignedInteger(Value)) 1617251ede7SZachary Turner return EC; 1627251ede7SZachary Turner } 1637251ede7SZachary Turner } else { 1647251ede7SZachary Turner APSInt N; 1657251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1667251ede7SZachary Turner return EC; 1677251ede7SZachary Turner Value = N.getExtValue(); 1687251ede7SZachary Turner } 1697251ede7SZachary Turner 1707251ede7SZachary Turner return Error::success(); 1717251ede7SZachary Turner } 1727251ede7SZachary Turner 1736e407669SNilanjana Basu Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value, 1746e407669SNilanjana Basu const Twine &Comment) { 175faed8516SNilanjana Basu if (isStreaming()) 1766e407669SNilanjana Basu emitEncodedUnsignedInteger(Value, Comment); 177faed8516SNilanjana Basu else if (isWriting()) { 1787251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(Value)) 1797251ede7SZachary Turner return EC; 1807251ede7SZachary Turner } else { 1817251ede7SZachary Turner APSInt N; 1827251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1837251ede7SZachary Turner return EC; 1847251ede7SZachary Turner Value = N.getZExtValue(); 1857251ede7SZachary Turner } 1867251ede7SZachary Turner return Error::success(); 1877251ede7SZachary Turner } 1887251ede7SZachary Turner 1896e407669SNilanjana Basu Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value, const Twine &Comment) { 190faed8516SNilanjana Basu if (isStreaming()) { 191faed8516SNilanjana Basu if (Value.isSigned()) 1926e407669SNilanjana Basu emitEncodedSignedInteger(Value.getSExtValue(), Comment); 193faed8516SNilanjana Basu else 1946e407669SNilanjana Basu emitEncodedUnsignedInteger(Value.getZExtValue(), Comment); 195faed8516SNilanjana Basu } else if (isWriting()) { 1967251ede7SZachary Turner if (Value.isSigned()) 1977251ede7SZachary Turner return writeEncodedSignedInteger(Value.getSExtValue()); 1987251ede7SZachary Turner return writeEncodedUnsignedInteger(Value.getZExtValue()); 199faed8516SNilanjana Basu } else 2007251ede7SZachary Turner return consume(*Reader, Value); 201faed8516SNilanjana Basu return Error::success(); 2027251ede7SZachary Turner } 2037251ede7SZachary Turner 2046e407669SNilanjana Basu Error CodeViewRecordIO::mapStringZ(StringRef &Value, const Twine &Comment) { 205faed8516SNilanjana Basu if (isStreaming()) { 206faed8516SNilanjana Basu auto NullTerminatedString = StringRef(Value.data(), Value.size() + 1); 2076e407669SNilanjana Basu emitComment(Comment); 208*a55daa14SFangrui Song Streamer->emitBytes(NullTerminatedString); 209faed8516SNilanjana Basu incrStreamedLen(NullTerminatedString.size()); 210faed8516SNilanjana Basu } else if (isWriting()) { 2114efa0a42SZachary Turner // Truncate if we attempt to write too much. 2124efa0a42SZachary Turner StringRef S = Value.take_front(maxFieldLength() - 1); 213120faca4SZachary Turner if (auto EC = Writer->writeCString(S)) 2147251ede7SZachary Turner return EC; 2157251ede7SZachary Turner } else { 216120faca4SZachary Turner if (auto EC = Reader->readCString(Value)) 2177251ede7SZachary Turner return EC; 2187251ede7SZachary Turner } 2197251ede7SZachary Turner return Error::success(); 2207251ede7SZachary Turner } 2217251ede7SZachary Turner 2226e407669SNilanjana Basu Error CodeViewRecordIO::mapGuid(GUID &Guid, const Twine &Comment) { 2234efa0a42SZachary Turner constexpr uint32_t GuidSize = 16; 224faed8516SNilanjana Basu 225faed8516SNilanjana Basu if (isStreaming()) { 226faed8516SNilanjana Basu StringRef GuidSR = 227faed8516SNilanjana Basu StringRef((reinterpret_cast<const char *>(&Guid)), GuidSize); 2286e407669SNilanjana Basu emitComment(Comment); 229*a55daa14SFangrui Song Streamer->emitBytes(GuidSR); 230faed8516SNilanjana Basu incrStreamedLen(GuidSize); 231faed8516SNilanjana Basu return Error::success(); 232faed8516SNilanjana Basu } 233faed8516SNilanjana Basu 2344efa0a42SZachary Turner if (maxFieldLength() < GuidSize) 2354efa0a42SZachary Turner return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 2364efa0a42SZachary Turner 2377251ede7SZachary Turner if (isWriting()) { 23867653ee0SReid Kleckner if (auto EC = Writer->writeBytes(Guid.Guid)) 2397251ede7SZachary Turner return EC; 2407251ede7SZachary Turner } else { 24167653ee0SReid Kleckner ArrayRef<uint8_t> GuidBytes; 24267653ee0SReid Kleckner if (auto EC = Reader->readBytes(GuidBytes, GuidSize)) 2437251ede7SZachary Turner return EC; 24467653ee0SReid Kleckner memcpy(Guid.Guid, GuidBytes.data(), GuidSize); 2457251ede7SZachary Turner } 2467251ede7SZachary Turner return Error::success(); 2477251ede7SZachary Turner } 2487251ede7SZachary Turner 2496e407669SNilanjana Basu Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value, 2506e407669SNilanjana Basu const Twine &Comment) { 251faed8516SNilanjana Basu 252faed8516SNilanjana Basu if (!isReading()) { 2536e407669SNilanjana Basu emitComment(Comment); 25446225b19SZachary Turner for (auto V : Value) { 25546225b19SZachary Turner if (auto EC = mapStringZ(V)) 25646225b19SZachary Turner return EC; 25746225b19SZachary Turner } 258faed8516SNilanjana Basu uint8_t FinalZero = 0; 259faed8516SNilanjana Basu if (auto EC = mapInteger(FinalZero)) 26046225b19SZachary Turner return EC; 26146225b19SZachary Turner } else { 26246225b19SZachary Turner StringRef S; 26346225b19SZachary Turner if (auto EC = mapStringZ(S)) 26446225b19SZachary Turner return EC; 26546225b19SZachary Turner while (!S.empty()) { 26646225b19SZachary Turner Value.push_back(S); 26746225b19SZachary Turner if (auto EC = mapStringZ(S)) 26846225b19SZachary Turner return EC; 26946225b19SZachary Turner }; 27046225b19SZachary Turner } 27146225b19SZachary Turner return Error::success(); 27246225b19SZachary Turner } 27346225b19SZachary Turner 2746e407669SNilanjana Basu void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value, 2756e407669SNilanjana Basu const Twine &Comment) { 276faed8516SNilanjana Basu assert(Value < 0 && "Encoded integer is not signed!"); 277faed8516SNilanjana Basu if (Value >= std::numeric_limits<int8_t>::min()) { 278faed8516SNilanjana Basu Streamer->EmitIntValue(LF_CHAR, 2); 2796e407669SNilanjana Basu emitComment(Comment); 280faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 1); 281faed8516SNilanjana Basu incrStreamedLen(3); 282faed8516SNilanjana Basu } else if (Value >= std::numeric_limits<int16_t>::min()) { 283faed8516SNilanjana Basu Streamer->EmitIntValue(LF_SHORT, 2); 2846e407669SNilanjana Basu emitComment(Comment); 285faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 2); 286faed8516SNilanjana Basu incrStreamedLen(4); 287faed8516SNilanjana Basu } else if (Value >= std::numeric_limits<int32_t>::min()) { 288faed8516SNilanjana Basu Streamer->EmitIntValue(LF_LONG, 2); 2896e407669SNilanjana Basu emitComment(Comment); 290faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 4); 291faed8516SNilanjana Basu incrStreamedLen(6); 292faed8516SNilanjana Basu } else { 293faed8516SNilanjana Basu Streamer->EmitIntValue(LF_QUADWORD, 2); 2946e407669SNilanjana Basu emitComment(Comment); 295faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 4); 296faed8516SNilanjana Basu incrStreamedLen(6); 297faed8516SNilanjana Basu } 298faed8516SNilanjana Basu } 299faed8516SNilanjana Basu 3006e407669SNilanjana Basu void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value, 3016e407669SNilanjana Basu const Twine &Comment) { 302faed8516SNilanjana Basu if (Value < LF_NUMERIC) { 3036e407669SNilanjana Basu emitComment(Comment); 304faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 2); 305faed8516SNilanjana Basu incrStreamedLen(2); 306faed8516SNilanjana Basu } else if (Value <= std::numeric_limits<uint16_t>::max()) { 307faed8516SNilanjana Basu Streamer->EmitIntValue(LF_USHORT, 2); 3086e407669SNilanjana Basu emitComment(Comment); 309faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 2); 310faed8516SNilanjana Basu incrStreamedLen(4); 311faed8516SNilanjana Basu } else if (Value <= std::numeric_limits<uint32_t>::max()) { 312faed8516SNilanjana Basu Streamer->EmitIntValue(LF_ULONG, 2); 3136e407669SNilanjana Basu emitComment(Comment); 314faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 4); 315faed8516SNilanjana Basu incrStreamedLen(6); 316faed8516SNilanjana Basu } else { 317faed8516SNilanjana Basu Streamer->EmitIntValue(LF_UQUADWORD, 2); 3186e407669SNilanjana Basu emitComment(Comment); 319faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 8); 320faed8516SNilanjana Basu incrStreamedLen(6); 321faed8516SNilanjana Basu } 322faed8516SNilanjana Basu } 323faed8516SNilanjana Basu 3247251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { 3257251ede7SZachary Turner assert(Value < 0 && "Encoded integer is not signed!"); 3267251ede7SZachary Turner if (Value >= std::numeric_limits<int8_t>::min()) { 327695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR)) 3287251ede7SZachary Turner return EC; 329695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int8_t>(Value)) 3307251ede7SZachary Turner return EC; 3317251ede7SZachary Turner } else if (Value >= std::numeric_limits<int16_t>::min()) { 332695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT)) 3337251ede7SZachary Turner return EC; 334695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int16_t>(Value)) 3357251ede7SZachary Turner return EC; 3367251ede7SZachary Turner } else if (Value >= std::numeric_limits<int32_t>::min()) { 337695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG)) 3387251ede7SZachary Turner return EC; 339695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int32_t>(Value)) 3407251ede7SZachary Turner return EC; 3417251ede7SZachary Turner } else { 342695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD)) 3437251ede7SZachary Turner return EC; 344695ed56bSZachary Turner if (auto EC = Writer->writeInteger(Value)) 3457251ede7SZachary Turner return EC; 3467251ede7SZachary Turner } 3477251ede7SZachary Turner return Error::success(); 3487251ede7SZachary Turner } 3497251ede7SZachary Turner 3507251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) { 3517251ede7SZachary Turner if (Value < LF_NUMERIC) { 352695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(Value)) 3537251ede7SZachary Turner return EC; 3547251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint16_t>::max()) { 355695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT)) 3567251ede7SZachary Turner return EC; 357695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(Value)) 3587251ede7SZachary Turner return EC; 3597251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint32_t>::max()) { 360695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG)) 3617251ede7SZachary Turner return EC; 362695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint32_t>(Value)) 3637251ede7SZachary Turner return EC; 3647251ede7SZachary Turner } else { 365695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD)) 3667251ede7SZachary Turner return EC; 367695ed56bSZachary Turner if (auto EC = Writer->writeInteger(Value)) 3687251ede7SZachary Turner return EC; 3697251ede7SZachary Turner } 3707251ede7SZachary Turner 3717251ede7SZachary Turner return Error::success(); 3727251ede7SZachary Turner } 373