1*7251ede7SZachary Turner //===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===//
2*7251ede7SZachary Turner //
3*7251ede7SZachary Turner //                     The LLVM Compiler Infrastructure
4*7251ede7SZachary Turner //
5*7251ede7SZachary Turner // This file is distributed under the University of Illinois Open Source
6*7251ede7SZachary Turner // License. See LICENSE.TXT for details.
7*7251ede7SZachary Turner //
8*7251ede7SZachary Turner //===----------------------------------------------------------------------===//
9*7251ede7SZachary Turner 
10*7251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h"
11*7251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/CodeView.h"
12*7251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
13*7251ede7SZachary Turner #include "llvm/DebugInfo/MSF/StreamReader.h"
14*7251ede7SZachary Turner #include "llvm/DebugInfo/MSF/StreamWriter.h"
15*7251ede7SZachary Turner 
16*7251ede7SZachary Turner using namespace llvm;
17*7251ede7SZachary Turner using namespace llvm::codeview;
18*7251ede7SZachary Turner 
19*7251ede7SZachary Turner Error CodeViewRecordIO::beginRecord(uint16_t Kind) {
20*7251ede7SZachary Turner   assert(!CurrentRecord.hasValue() && "There is already a record active!");
21*7251ede7SZachary Turner   CurrentRecord.emplace();
22*7251ede7SZachary Turner 
23*7251ede7SZachary Turner   CurrentRecord->Kind = Kind;
24*7251ede7SZachary Turner   return Error::success();
25*7251ede7SZachary Turner }
26*7251ede7SZachary Turner 
27*7251ede7SZachary Turner Error CodeViewRecordIO::endRecord() {
28*7251ede7SZachary Turner   assert(CurrentRecord.hasValue() && "Not in a record!");
29*7251ede7SZachary Turner   CurrentRecord.reset();
30*7251ede7SZachary Turner   return Error::success();
31*7251ede7SZachary Turner }
32*7251ede7SZachary Turner 
33*7251ede7SZachary Turner Error CodeViewRecordIO::skipPadding() {
34*7251ede7SZachary Turner   assert(!isWriting() && "Cannot skip padding while writing!");
35*7251ede7SZachary Turner 
36*7251ede7SZachary Turner   if (Reader->bytesRemaining() == 0)
37*7251ede7SZachary Turner     return Error::success();
38*7251ede7SZachary Turner 
39*7251ede7SZachary Turner   uint8_t Leaf = Reader->peek();
40*7251ede7SZachary Turner   if (Leaf < LF_PAD0)
41*7251ede7SZachary Turner     return Error::success();
42*7251ede7SZachary Turner   // Leaf is greater than 0xf0. We should advance by the number of bytes in
43*7251ede7SZachary Turner   // the low 4 bits.
44*7251ede7SZachary Turner   unsigned BytesToAdvance = Leaf & 0x0F;
45*7251ede7SZachary Turner   return Reader->skip(BytesToAdvance);
46*7251ede7SZachary Turner }
47*7251ede7SZachary Turner 
48*7251ede7SZachary Turner Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) {
49*7251ede7SZachary Turner   if (isWriting()) {
50*7251ede7SZachary Turner     if (auto EC = Writer->writeBytes(Bytes))
51*7251ede7SZachary Turner       return EC;
52*7251ede7SZachary Turner   } else {
53*7251ede7SZachary Turner     if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining()))
54*7251ede7SZachary Turner       return EC;
55*7251ede7SZachary Turner   }
56*7251ede7SZachary Turner   return Error::success();
57*7251ede7SZachary Turner }
58*7251ede7SZachary Turner 
59*7251ede7SZachary Turner Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) {
60*7251ede7SZachary Turner   if (isWriting()) {
61*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
62*7251ede7SZachary Turner       return EC;
63*7251ede7SZachary Turner     return Error::success();
64*7251ede7SZachary Turner   }
65*7251ede7SZachary Turner 
66*7251ede7SZachary Turner   uint32_t I;
67*7251ede7SZachary Turner   if (auto EC = Reader->readInteger(I))
68*7251ede7SZachary Turner     return EC;
69*7251ede7SZachary Turner   TypeInd.setIndex(I);
70*7251ede7SZachary Turner   return Error::success();
71*7251ede7SZachary Turner }
72*7251ede7SZachary Turner 
73*7251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) {
74*7251ede7SZachary Turner   if (isWriting()) {
75*7251ede7SZachary Turner     if (Value >= 0) {
76*7251ede7SZachary Turner       if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
77*7251ede7SZachary Turner         return EC;
78*7251ede7SZachary Turner     } else {
79*7251ede7SZachary Turner       if (auto EC = writeEncodedSignedInteger(Value))
80*7251ede7SZachary Turner         return EC;
81*7251ede7SZachary Turner     }
82*7251ede7SZachary Turner   } else {
83*7251ede7SZachary Turner     APSInt N;
84*7251ede7SZachary Turner     if (auto EC = consume(*Reader, N))
85*7251ede7SZachary Turner       return EC;
86*7251ede7SZachary Turner     Value = N.getExtValue();
87*7251ede7SZachary Turner   }
88*7251ede7SZachary Turner 
89*7251ede7SZachary Turner   return Error::success();
90*7251ede7SZachary Turner }
91*7251ede7SZachary Turner 
92*7251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) {
93*7251ede7SZachary Turner   if (isWriting()) {
94*7251ede7SZachary Turner     if (auto EC = writeEncodedUnsignedInteger(Value))
95*7251ede7SZachary Turner       return EC;
96*7251ede7SZachary Turner   } else {
97*7251ede7SZachary Turner     APSInt N;
98*7251ede7SZachary Turner     if (auto EC = consume(*Reader, N))
99*7251ede7SZachary Turner       return EC;
100*7251ede7SZachary Turner     Value = N.getZExtValue();
101*7251ede7SZachary Turner   }
102*7251ede7SZachary Turner   return Error::success();
103*7251ede7SZachary Turner }
104*7251ede7SZachary Turner 
105*7251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) {
106*7251ede7SZachary Turner   if (isWriting()) {
107*7251ede7SZachary Turner     if (Value.isSigned())
108*7251ede7SZachary Turner       return writeEncodedSignedInteger(Value.getSExtValue());
109*7251ede7SZachary Turner     return writeEncodedUnsignedInteger(Value.getZExtValue());
110*7251ede7SZachary Turner   }
111*7251ede7SZachary Turner 
112*7251ede7SZachary Turner   return consume(*Reader, Value);
113*7251ede7SZachary Turner }
114*7251ede7SZachary Turner 
115*7251ede7SZachary Turner Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
116*7251ede7SZachary Turner   if (isWriting()) {
117*7251ede7SZachary Turner     if (auto EC = Writer->writeZeroString(Value))
118*7251ede7SZachary Turner       return EC;
119*7251ede7SZachary Turner   } else {
120*7251ede7SZachary Turner     if (auto EC = Reader->readZeroString(Value))
121*7251ede7SZachary Turner       return EC;
122*7251ede7SZachary Turner   }
123*7251ede7SZachary Turner   return Error::success();
124*7251ede7SZachary Turner }
125*7251ede7SZachary Turner 
126*7251ede7SZachary Turner Error CodeViewRecordIO::mapGuid(StringRef &Guid) {
127*7251ede7SZachary Turner   if (isWriting()) {
128*7251ede7SZachary Turner     assert(Guid.size() == 16 && "Invalid Guid Size!");
129*7251ede7SZachary Turner     if (auto EC = Writer->writeFixedString(Guid))
130*7251ede7SZachary Turner       return EC;
131*7251ede7SZachary Turner   } else {
132*7251ede7SZachary Turner     if (auto EC = Reader->readFixedString(Guid, 16))
133*7251ede7SZachary Turner       return EC;
134*7251ede7SZachary Turner   }
135*7251ede7SZachary Turner   return Error::success();
136*7251ede7SZachary Turner }
137*7251ede7SZachary Turner 
138*7251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
139*7251ede7SZachary Turner   assert(Value < 0 && "Encoded integer is not signed!");
140*7251ede7SZachary Turner   if (Value >= std::numeric_limits<int8_t>::min()) {
141*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_CHAR)))
142*7251ede7SZachary Turner       return EC;
143*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<int8_t>(Value)))
144*7251ede7SZachary Turner       return EC;
145*7251ede7SZachary Turner   } else if (Value >= std::numeric_limits<int16_t>::min()) {
146*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_SHORT)))
147*7251ede7SZachary Turner       return EC;
148*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<int16_t>(Value)))
149*7251ede7SZachary Turner       return EC;
150*7251ede7SZachary Turner   } else if (Value >= std::numeric_limits<int32_t>::min()) {
151*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_LONG)))
152*7251ede7SZachary Turner       return EC;
153*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<int32_t>(Value)))
154*7251ede7SZachary Turner       return EC;
155*7251ede7SZachary Turner   } else {
156*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_QUADWORD)))
157*7251ede7SZachary Turner       return EC;
158*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(Value))
159*7251ede7SZachary Turner       return EC;
160*7251ede7SZachary Turner   }
161*7251ede7SZachary Turner   return Error::success();
162*7251ede7SZachary Turner }
163*7251ede7SZachary Turner 
164*7251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
165*7251ede7SZachary Turner   if (Value < LF_NUMERIC) {
166*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
167*7251ede7SZachary Turner       return EC;
168*7251ede7SZachary Turner   } else if (Value <= std::numeric_limits<uint16_t>::max()) {
169*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_USHORT)))
170*7251ede7SZachary Turner       return EC;
171*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
172*7251ede7SZachary Turner       return EC;
173*7251ede7SZachary Turner   } else if (Value <= std::numeric_limits<uint32_t>::max()) {
174*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_ULONG)))
175*7251ede7SZachary Turner       return EC;
176*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<uint32_t>(Value)))
177*7251ede7SZachary Turner       return EC;
178*7251ede7SZachary Turner   } else {
179*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_UQUADWORD)))
180*7251ede7SZachary Turner       return EC;
181*7251ede7SZachary Turner     if (auto EC = Writer->writeInteger(Value))
182*7251ede7SZachary Turner       return EC;
183*7251ede7SZachary Turner   }
184*7251ede7SZachary Turner 
185*7251ede7SZachary Turner   return Error::success();
186*7251ede7SZachary Turner }
187