summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp49
-rw-r--r--llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp15
-rw-r--r--llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp126
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp19
4 files changed, 177 insertions, 32 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 9f8ed86b50e..61fe6984338 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -51,6 +51,7 @@
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfoMetadata.h"
@@ -94,6 +95,24 @@
using namespace llvm;
using namespace llvm::codeview;
+namespace {
+class CVMCAdapter : public CodeViewRecordStreamer {
+public:
+ CVMCAdapter(MCStreamer &OS) : OS(&OS) {}
+
+ void EmitBytes(StringRef Data) { OS->EmitBytes(Data); }
+
+ void EmitIntValue(uint64_t Value, unsigned Size) {
+ OS->EmitIntValue(Value, Size);
+ }
+
+ void EmitBinaryData(StringRef Data) { OS->EmitBinaryData(Data); }
+
+private:
+ MCStreamer *OS = nullptr;
+};
+} // namespace
+
static CPUType mapArchToCVCPUType(Triple::ArchType Type) {
switch (Type) {
case Triple::ArchType::x86:
@@ -617,26 +636,40 @@ void CodeViewDebug::emitTypeInformation() {
// This will fail if the record data is invalid.
CVType Record = Table.getType(*B);
+ TypeVisitorCallbackPipeline Pipeline;
+ CVMCAdapter CVMCOS(OS);
+ TypeRecordMapping typeMapping(CVMCOS);
+ SmallString<512> CommentBlock;
+ raw_svector_ostream CommentOS(CommentBlock);
+
if (OS.isVerboseAsm()) {
// Emit a block comment describing the type record for readability.
- SmallString<512> CommentBlock;
- raw_svector_ostream CommentOS(CommentBlock);
ScopedPrinter SP(CommentOS);
SP.setPrefix(CommentPrefix);
TypeDumpVisitor TDV(Table, &SP, false);
+ Pipeline.addCallbackToPipeline(TDV);
+ }
+ Pipeline.addCallbackToPipeline(typeMapping);
- Error E = codeview::visitTypeRecord(Record, *B, TDV);
- if (E) {
- logAllUnhandledErrors(std::move(E), errs(), "error: ");
- llvm_unreachable("produced malformed type record");
- }
+ auto RecordLen = Record.length();
+ auto RecordKind = Record.kind();
+ OS.EmitIntValue(RecordLen - 2, 2);
+ OS.EmitIntValue(RecordKind, sizeof(RecordKind));
+
+ Error E = codeview::visitTypeRecord(Record, *B, Pipeline);
+
+ if (E) {
+ logAllUnhandledErrors(std::move(E), errs(), "error: ");
+ llvm_unreachable("produced malformed type record");
+ }
+
+ if (OS.isVerboseAsm()) {
// emitRawComment will insert its own tab and comment string before
// the first line, so strip off our first one. It also prints its own
// newline.
OS.emitRawComment(
CommentOS.str().drop_front(CommentPrefix.size() - 1).rtrim());
}
- OS.EmitBinaryData(Record.str_data());
B = Table.getNext(*B);
}
}
diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index dd6f75f97a4..ec4773d571c 100644
--- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -209,6 +209,14 @@ struct VisitHelper {
}
}
+ VisitHelper(TypeVisitorCallbackPipeline &Callbacks, VisitorDataSource Source)
+ : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
+ if (Source == VDS_BytesPresent) {
+ Pipeline = Callbacks;
+ Pipeline.addCallbackToPipelineFront(Deserializer);
+ }
+ }
+
TypeDeserializer Deserializer;
TypeVisitorCallbackPipeline Pipeline;
CVTypeVisitor Visitor;
@@ -222,6 +230,13 @@ Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
return V.Visitor.visitTypeRecord(Record, Index);
}
+Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
+ TypeVisitorCallbackPipeline &Callbacks,
+ VisitorDataSource Source) {
+ VisitHelper V(Callbacks, Source);
+ return V.Visitor.visitTypeRecord(Record, Index);
+}
+
Error llvm::codeview::visitTypeRecord(CVType &Record,
TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source) {
diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
index 92c795ab8fa..2b69a1e0768 100644
--- a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
+++ b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
@@ -20,6 +20,7 @@ Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) {
Limit.MaxLength = MaxLength;
Limit.BeginOffset = getCurrentOffset();
Limits.push_back(Limit);
+ resetStreamedLen();
return Error::success();
}
@@ -34,10 +35,29 @@ Error CodeViewRecordIO::endRecord() {
// we don't know how big the record is until we're finished writing it, so
// even though we don't commit the extraneous data, we still can't guarantee
// we're at the end of the allocated data.
+
+ if (isStreaming()) {
+ // For streaming mode, add padding to align with 4 byte boundaries for each
+ // record
+ uint32_t Align = getStreamedLen() % 4;
+ if (Align == 0)
+ return Error::success();
+
+ int PaddingBytes = 4 - Align;
+ while (PaddingBytes > 0) {
+ char Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);
+ StringRef BytesSR = StringRef(&Pad, sizeof(Pad));
+ Streamer->EmitBytes(BytesSR);
+ --PaddingBytes;
+ }
+ }
return Error::success();
}
uint32_t CodeViewRecordIO::maxFieldLength() const {
+ if (isStreaming())
+ return 0;
+
assert(!Limits.empty() && "Not in a record!");
// The max length of the next field is the minimum of all lengths that would
@@ -78,7 +98,10 @@ Error CodeViewRecordIO::skipPadding() {
}
Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) {
- if (isWriting()) {
+ if (isStreaming()) {
+ Streamer->EmitBinaryData(toStringRef(Bytes));
+ incrStreamedLen(Bytes.size());
+ } else if (isWriting()) {
if (auto EC = Writer->writeBytes(Bytes))
return EC;
} else {
@@ -99,21 +122,28 @@ Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes) {
}
Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) {
- if (isWriting()) {
+ if (isStreaming()) {
+ Streamer->EmitIntValue(TypeInd.getIndex(), sizeof(TypeInd.getIndex()));
+ incrStreamedLen(sizeof(TypeInd.getIndex()));
+ } else if (isWriting()) {
if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
return EC;
- return Error::success();
+ } else {
+ uint32_t I;
+ if (auto EC = Reader->readInteger(I))
+ return EC;
+ TypeInd.setIndex(I);
}
-
- 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 (isStreaming()) {
+ if (Value >= 0)
+ emitEncodedUnsignedInteger(static_cast<uint64_t>(Value));
+ else
+ emitEncodedSignedInteger(Value);
+ } else if (isWriting()) {
if (Value >= 0) {
if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
return EC;
@@ -132,7 +162,9 @@ Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) {
}
Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) {
- if (isWriting()) {
+ if (isStreaming())
+ emitEncodedUnsignedInteger(Value);
+ else if (isWriting()) {
if (auto EC = writeEncodedUnsignedInteger(Value))
return EC;
} else {
@@ -145,17 +177,26 @@ Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) {
}
Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) {
- if (isWriting()) {
+ if (isStreaming()) {
+ if (Value.isSigned())
+ emitEncodedSignedInteger(Value.getSExtValue());
+ else
+ emitEncodedUnsignedInteger(Value.getZExtValue());
+ } else if (isWriting()) {
if (Value.isSigned())
return writeEncodedSignedInteger(Value.getSExtValue());
return writeEncodedUnsignedInteger(Value.getZExtValue());
- }
-
- return consume(*Reader, Value);
+ } else
+ return consume(*Reader, Value);
+ return Error::success();
}
Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
- if (isWriting()) {
+ if (isStreaming()) {
+ auto NullTerminatedString = StringRef(Value.data(), Value.size() + 1);
+ Streamer->EmitBytes(NullTerminatedString);
+ incrStreamedLen(NullTerminatedString.size());
+ } else if (isWriting()) {
// Truncate if we attempt to write too much.
StringRef S = Value.take_front(maxFieldLength() - 1);
if (auto EC = Writer->writeCString(S))
@@ -169,6 +210,15 @@ Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
Error CodeViewRecordIO::mapGuid(GUID &Guid) {
constexpr uint32_t GuidSize = 16;
+
+ if (isStreaming()) {
+ StringRef GuidSR =
+ StringRef((reinterpret_cast<const char *>(&Guid)), GuidSize);
+ Streamer->EmitBytes(GuidSR);
+ incrStreamedLen(GuidSize);
+ return Error::success();
+ }
+
if (maxFieldLength() < GuidSize)
return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
@@ -185,12 +235,14 @@ Error CodeViewRecordIO::mapGuid(GUID &Guid) {
}
Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) {
- if (isWriting()) {
+
+ if (!isReading()) {
for (auto V : Value) {
if (auto EC = mapStringZ(V))
return EC;
}
- if (auto EC = Writer->writeInteger<uint8_t>(0))
+ uint8_t FinalZero = 0;
+ if (auto EC = mapInteger(FinalZero))
return EC;
} else {
StringRef S;
@@ -205,6 +257,46 @@ Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) {
return Error::success();
}
+void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value) {
+ assert(Value < 0 && "Encoded integer is not signed!");
+ if (Value >= std::numeric_limits<int8_t>::min()) {
+ Streamer->EmitIntValue(LF_CHAR, 2);
+ Streamer->EmitIntValue(Value, 1);
+ incrStreamedLen(3);
+ } else if (Value >= std::numeric_limits<int16_t>::min()) {
+ Streamer->EmitIntValue(LF_SHORT, 2);
+ Streamer->EmitIntValue(Value, 2);
+ incrStreamedLen(4);
+ } else if (Value >= std::numeric_limits<int32_t>::min()) {
+ Streamer->EmitIntValue(LF_LONG, 2);
+ Streamer->EmitIntValue(Value, 4);
+ incrStreamedLen(6);
+ } else {
+ Streamer->EmitIntValue(LF_QUADWORD, 2);
+ Streamer->EmitIntValue(Value, 4);
+ incrStreamedLen(6);
+ }
+}
+
+void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value) {
+ if (Value < LF_NUMERIC) {
+ Streamer->EmitIntValue(Value, 2);
+ incrStreamedLen(2);
+ } else if (Value <= std::numeric_limits<uint16_t>::max()) {
+ Streamer->EmitIntValue(LF_USHORT, 2);
+ Streamer->EmitIntValue(Value, 2);
+ incrStreamedLen(4);
+ } else if (Value <= std::numeric_limits<uint32_t>::max()) {
+ Streamer->EmitIntValue(LF_ULONG, 2);
+ Streamer->EmitIntValue(Value, 4);
+ incrStreamedLen(6);
+ } else {
+ Streamer->EmitIntValue(LF_UQUADWORD, 2);
+ Streamer->EmitIntValue(Value, 8);
+ incrStreamedLen(6);
+ }
+}
+
Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
assert(Value < 0 && "Encoded integer is not signed!");
if (Value >= std::numeric_limits<int8_t>::min()) {
diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
index 12fb50d6ddc..104e310d41b 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
@@ -29,7 +29,7 @@ struct MapOneMethodRecord {
error(IO.mapInteger(Method.Type));
if (Method.isIntroducingVirtual()) {
error(IO.mapInteger(Method.VFTableOffset));
- } else if (!IO.isWriting())
+ } else if (IO.isReading())
Method.VFTableOffset = -1;
if (!IsFromOverloadList)
@@ -72,6 +72,9 @@ static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name,
error(IO.mapStringZ(N));
}
} else {
+ // Reading & Streaming mode come after writing mode is executed for each
+ // record. Truncating large names are done during writing, so its not
+ // necessary to do it while reading or streaming.
error(IO.mapStringZ(Name));
if (HasUniqueName)
error(IO.mapStringZ(UniqueName));
@@ -96,6 +99,10 @@ Error TypeRecordMapping::visitTypeBegin(CVType &CVR) {
return Error::success();
}
+Error TypeRecordMapping::visitTypeBegin(CVType &CVR, TypeIndex Index) {
+ return visitTypeBegin(CVR);
+}
+
Error TypeRecordMapping::visitTypeEnd(CVType &Record) {
assert(TypeKind.hasValue() && "Not in a type mapping!");
assert(!MemberKind.hasValue() && "Still in a member mapping!");
@@ -126,7 +133,7 @@ Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) {
assert(TypeKind.hasValue() && "Not in a type mapping!");
assert(MemberKind.hasValue() && "Not in a member mapping!");
- if (!IO.isWriting()) {
+ if (IO.isReading()) {
if (auto EC = IO.skipPadding())
return EC;
}
@@ -139,7 +146,6 @@ Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) {
Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) {
error(IO.mapInteger(Record.ModifiedType));
error(IO.mapEnum(Record.Modifiers));
-
return Error::success();
}
@@ -172,7 +178,6 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) {
error(IO.mapVectorN<uint32_t>(
Record.ArgIndices,
[](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
-
return Error::success();
}
@@ -190,7 +195,7 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) {
error(IO.mapInteger(Record.Attrs));
if (Record.isPointerToMember()) {
- if (!IO.isWriting())
+ if (IO.isReading())
Record.MemberInfo.emplace();
MemberPointerInfo &M = *Record.MemberInfo;
@@ -260,7 +265,7 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) {
Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
VFTableShapeRecord &Record) {
uint16_t Size;
- if (IO.isWriting()) {
+ if (!IO.isReading()) {
ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
Size = Slots.size();
error(IO.mapInteger(Size));
@@ -291,7 +296,7 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) {
error(IO.mapInteger(Record.OverriddenVFTable));
error(IO.mapInteger(Record.VFPtrOffset));
uint32_t NamesLen = 0;
- if (IO.isWriting()) {
+ if (!IO.isReading()) {
for (auto Name : Record.MethodNames)
NamesLen += Name.size() + 1;
}
OpenPOWER on IntegriCloud