summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2016-11-02 17:05:19 +0000
committerZachary Turner <zturner@google.com>2016-11-02 17:05:19 +0000
commit7251ede7c5ee82d25e309b6a30952a6b5e7c1f89 (patch)
tree3b4fb352c4fb41db708e3778d3e1aef75a47eed0 /llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
parent368972c3b3b8ad62fa064b495223809074c39115 (diff)
downloadbcm5719-llvm-7251ede7c5ee82d25e309b6a30952a6b5e7c1f89.tar.gz
bcm5719-llvm-7251ede7c5ee82d25e309b6a30952a6b5e7c1f89.zip
Add CodeViewRecordIO for reading and writing.
Using a pattern similar to that of YamlIO, this allows us to have a single codepath for translating codeview records to and from serialized byte streams. The current patch only hooks this up to the reading of CodeView type records. A subsequent patch will hook it up for writing of CodeView type records, and then a third patch will hook up the reading and writing of CodeView symbols. Differential Revision: https://reviews.llvm.org/D26040 llvm-svn: 285836
Diffstat (limited to 'llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp')
-rw-r--r--llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp186
1 files changed, 186 insertions, 0 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
new file mode 100644
index 00000000000..7841e4f2f6a
--- /dev/null
+++ b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
@@ -0,0 +1,186 @@
+//===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamWriter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error CodeViewRecordIO::beginRecord(uint16_t Kind) {
+ assert(!CurrentRecord.hasValue() && "There is already a record active!");
+ CurrentRecord.emplace();
+
+ CurrentRecord->Kind = Kind;
+ return Error::success();
+}
+
+Error CodeViewRecordIO::endRecord() {
+ assert(CurrentRecord.hasValue() && "Not in a record!");
+ CurrentRecord.reset();
+ return Error::success();
+}
+
+Error CodeViewRecordIO::skipPadding() {
+ assert(!isWriting() && "Cannot skip padding while writing!");
+
+ if (Reader->bytesRemaining() == 0)
+ return Error::success();
+
+ uint8_t Leaf = Reader->peek();
+ if (Leaf < LF_PAD0)
+ return Error::success();
+ // Leaf is greater than 0xf0. We should advance by the number of bytes in
+ // the low 4 bits.
+ unsigned BytesToAdvance = Leaf & 0x0F;
+ return Reader->skip(BytesToAdvance);
+}
+
+Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) {
+ if (isWriting()) {
+ if (auto EC = Writer->writeBytes(Bytes))
+ return EC;
+ } else {
+ if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining()))
+ return EC;
+ }
+ return Error::success();
+}
+
+Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) {
+ if (isWriting()) {
+ if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
+ return EC;
+ return Error::success();
+ }
+
+ uint32_t I;
+ if (auto EC = Reader->readInteger(I))
+ return EC;
+ TypeInd.setIndex(I);
+ return Error::success();
+}
+
+Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) {
+ if (isWriting()) {
+ if (Value >= 0) {
+ if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
+ return EC;
+ } else {
+ if (auto EC = writeEncodedSignedInteger(Value))
+ return EC;
+ }
+ } else {
+ APSInt N;
+ if (auto EC = consume(*Reader, N))
+ return EC;
+ Value = N.getExtValue();
+ }
+
+ return Error::success();
+}
+
+Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) {
+ if (isWriting()) {
+ if (auto EC = writeEncodedUnsignedInteger(Value))
+ return EC;
+ } else {
+ APSInt N;
+ if (auto EC = consume(*Reader, N))
+ return EC;
+ Value = N.getZExtValue();
+ }
+ return Error::success();
+}
+
+Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) {
+ if (isWriting()) {
+ if (Value.isSigned())
+ return writeEncodedSignedInteger(Value.getSExtValue());
+ return writeEncodedUnsignedInteger(Value.getZExtValue());
+ }
+
+ return consume(*Reader, Value);
+}
+
+Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
+ if (isWriting()) {
+ if (auto EC = Writer->writeZeroString(Value))
+ return EC;
+ } else {
+ if (auto EC = Reader->readZeroString(Value))
+ return EC;
+ }
+ return Error::success();
+}
+
+Error CodeViewRecordIO::mapGuid(StringRef &Guid) {
+ if (isWriting()) {
+ assert(Guid.size() == 16 && "Invalid Guid Size!");
+ if (auto EC = Writer->writeFixedString(Guid))
+ return EC;
+ } else {
+ if (auto EC = Reader->readFixedString(Guid, 16))
+ return EC;
+ }
+ return Error::success();
+}
+
+Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
+ assert(Value < 0 && "Encoded integer is not signed!");
+ if (Value >= std::numeric_limits<int8_t>::min()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_CHAR)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<int8_t>(Value)))
+ return EC;
+ } else if (Value >= std::numeric_limits<int16_t>::min()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_SHORT)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<int16_t>(Value)))
+ return EC;
+ } else if (Value >= std::numeric_limits<int32_t>::min()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_LONG)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<int32_t>(Value)))
+ return EC;
+ } else {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_QUADWORD)))
+ return EC;
+ if (auto EC = Writer->writeInteger(Value))
+ return EC;
+ }
+ return Error::success();
+}
+
+Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
+ if (Value < LF_NUMERIC) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
+ return EC;
+ } else if (Value <= std::numeric_limits<uint16_t>::max()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_USHORT)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
+ return EC;
+ } else if (Value <= std::numeric_limits<uint32_t>::max()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_ULONG)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<uint32_t>(Value)))
+ return EC;
+ } else {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_UQUADWORD)))
+ return EC;
+ if (auto EC = Writer->writeInteger(Value))
+ return EC;
+ }
+
+ return Error::success();
+}
OpenPOWER on IntegriCloud