Changing CodeView debug info type record representation in assembly files to make...
authorNilanjana Basu <nilanjana.basu87@gmail.com>
Wed, 3 Jul 2019 00:26:23 +0000 (00:26 +0000)
committerNilanjana Basu <nilanjana.basu87@gmail.com>
Wed, 3 Jul 2019 00:26:23 +0000 (00:26 +0000)
llvm-svn: 364982

46 files changed:
llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h
llvm/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h
llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h
llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
llvm/test/DebugInfo/COFF/anonymous-struct.ll
llvm/test/DebugInfo/COFF/big-type.ll
llvm/test/DebugInfo/COFF/class-options-common.ll
llvm/test/DebugInfo/COFF/const-unnamed-member.ll
llvm/test/DebugInfo/COFF/defer-complete-type.ll
llvm/test/DebugInfo/COFF/enum-co.ll
llvm/test/DebugInfo/COFF/enum.ll
llvm/test/DebugInfo/COFF/function-options.ll
llvm/test/DebugInfo/COFF/globals.ll
llvm/test/DebugInfo/COFF/inheritance.ll
llvm/test/DebugInfo/COFF/inlining-padding.ll
llvm/test/DebugInfo/COFF/inlining-same-name.ll
llvm/test/DebugInfo/COFF/inlining.ll
llvm/test/DebugInfo/COFF/lambda.ll
llvm/test/DebugInfo/COFF/long-type-name.ll
llvm/test/DebugInfo/COFF/nested-types.ll
llvm/test/DebugInfo/COFF/retained-types.ll
llvm/test/DebugInfo/COFF/scopes.ll
llvm/test/DebugInfo/COFF/static-methods.ll
llvm/test/DebugInfo/COFF/type-quals.ll
llvm/test/DebugInfo/COFF/types-array-advanced.ll
llvm/test/DebugInfo/COFF/types-array-unsized.ll
llvm/test/DebugInfo/COFF/types-array.ll
llvm/test/DebugInfo/COFF/types-basic.ll
llvm/test/DebugInfo/COFF/types-calling-conv.ll
llvm/test/DebugInfo/COFF/types-cvarargs.ll
llvm/test/DebugInfo/COFF/types-data-members.ll
llvm/test/DebugInfo/COFF/types-empty-member-fn.ll
llvm/test/DebugInfo/COFF/types-method-ref-qualifiers.ll
llvm/test/DebugInfo/COFF/types-nested-class.ll
llvm/test/DebugInfo/COFF/types-non-virtual-methods.ll
llvm/test/DebugInfo/COFF/types-ptr-to-member.ll
llvm/test/DebugInfo/COFF/types-recursive-struct.ll
llvm/test/DebugInfo/COFF/unnamed.ll
llvm/test/DebugInfo/COFF/vftables.ll
llvm/test/DebugInfo/COFF/virtual-method-kinds.ll
llvm/test/DebugInfo/COFF/virtual-methods.ll
llvm/test/DebugInfo/COFF/vtable-optzn-array.ll

index 7538cb2..7d20bb0 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "llvm/DebugInfo/CodeView/CVRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
 #include "llvm/Support/Error.h"
 
 namespace llvm {
@@ -30,6 +31,9 @@ enum VisitorDataSource {
 Error visitTypeRecord(CVType &Record, TypeIndex Index,
                       TypeVisitorCallbacks &Callbacks,
                       VisitorDataSource Source = VDS_BytesPresent);
+Error visitTypeRecord(CVType &Record, TypeIndex Index,
+                      TypeVisitorCallbackPipeline &Callbacks,
+                      VisitorDataSource Source = VDS_BytesPresent);
 Error visitTypeRecord(CVType &Record, TypeVisitorCallbacks &Callbacks,
                       VisitorDataSource Source = VDS_BytesPresent);
 
index b2476f1..d3bad4c 100644 (file)
 #include <type_traits>
 
 namespace llvm {
+
 namespace codeview {
 
+class CodeViewRecordStreamer {
+public:
+  virtual void EmitBytes(StringRef Data) = 0;
+  virtual void EmitIntValue(uint64_t Value, unsigned Size) = 0;
+  virtual void EmitBinaryData(StringRef Data) = 0;
+  virtual ~CodeViewRecordStreamer() = default;
+};
+
 class CodeViewRecordIO {
   uint32_t getCurrentOffset() const {
-    return (isWriting()) ? Writer->getOffset() : Reader->getOffset();
+    if (isWriting())
+      return Writer->getOffset();
+    else if (isReading())
+      return Reader->getOffset();
+    else
+      return 0;
   }
 
 public:
+  // deserializes records to structures
   explicit CodeViewRecordIO(BinaryStreamReader &Reader) : Reader(&Reader) {}
+
+  // serializes records to buffer
   explicit CodeViewRecordIO(BinaryStreamWriter &Writer) : Writer(&Writer) {}
 
+  // writes records to assembly file using MC library interface
+  explicit CodeViewRecordIO(CodeViewRecordStreamer &Streamer)
+      : Streamer(&Streamer) {}
+
   Error beginRecord(Optional<uint32_t> MaxLength);
   Error endRecord();
 
   Error mapInteger(TypeIndex &TypeInd);
 
-  bool isReading() const { return Reader != nullptr; }
-  bool isWriting() const { return !isReading(); }
+  bool isStreaming() const {
+    return (Streamer != nullptr) && (Reader == nullptr) && (Writer == nullptr);
+  }
+  bool isReading() const {
+    return (Reader != nullptr) && (Streamer == nullptr) && (Writer == nullptr);
+  }
+  bool isWriting() const {
+    return (Writer != nullptr) && (Streamer == nullptr) && (Reader == nullptr);
+  }
 
   uint32_t maxFieldLength() const;
 
   template <typename T> Error mapObject(T &Value) {
+    if (isStreaming()) {
+      StringRef BytesSR =
+          StringRef((reinterpret_cast<const char *>(&Value)), sizeof(Value));
+      Streamer->EmitBytes(BytesSR);
+      incrStreamedLen(sizeof(T));
+      return Error::success();
+    }
+
     if (isWriting())
       return Writer->writeObject(Value);
 
@@ -57,6 +93,12 @@ public:
   }
 
   template <typename T> Error mapInteger(T &Value) {
+    if (isStreaming()) {
+      Streamer->EmitIntValue((int)Value, sizeof(T));
+      incrStreamedLen(sizeof(T));
+      return Error::success();
+    }
+
     if (isWriting())
       return Writer->writeInteger(Value);
 
@@ -64,18 +106,21 @@ public:
   }
 
   template <typename T> Error mapEnum(T &Value) {
-    if (sizeof(Value) > maxFieldLength())
+    if (!isStreaming() && sizeof(Value) > maxFieldLength())
       return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
 
     using U = typename std::underlying_type<T>::type;
     U X;
-    if (isWriting())
+
+    if (isWriting() || isStreaming())
       X = static_cast<U>(Value);
 
     if (auto EC = mapInteger(X))
       return EC;
+
     if (isReading())
       Value = static_cast<T>(X);
+
     return Error::success();
   }
 
@@ -90,7 +135,16 @@ public:
   template <typename SizeType, typename T, typename ElementMapper>
   Error mapVectorN(T &Items, const ElementMapper &Mapper) {
     SizeType Size;
-    if (isWriting()) {
+    if (isStreaming()) {
+      Size = static_cast<SizeType>(Items.size());
+      Streamer->EmitIntValue(Size, sizeof(Size));
+      incrStreamedLen(sizeof(Size)); // add 1 for the delimiter
+
+      for (auto &X : Items) {
+        if (auto EC = Mapper(*this, X))
+          return EC;
+      }
+    } else if (isWriting()) {
       Size = static_cast<SizeType>(Items.size());
       if (auto EC = Writer->writeInteger(Size))
         return EC;
@@ -115,7 +169,7 @@ public:
 
   template <typename T, typename ElementMapper>
   Error mapVectorTail(T &Items, const ElementMapper &Mapper) {
-    if (isWriting()) {
+    if (isStreaming() || isWriting()) {
       for (auto &Item : Items) {
         if (auto EC = Mapper(*this, Item))
           return EC;
@@ -138,10 +192,28 @@ public:
   Error padToAlignment(uint32_t Align);
   Error skipPadding();
 
+  uint64_t getStreamedLen() {
+    if (isStreaming())
+      return StreamedLen;
+    return 0;
+  }
+
 private:
+  void emitEncodedSignedInteger(const int64_t &Value);
+  void emitEncodedUnsignedInteger(const uint64_t &Value);
   Error writeEncodedSignedInteger(const int64_t &Value);
   Error writeEncodedUnsignedInteger(const uint64_t &Value);
 
+  void incrStreamedLen(const uint64_t &Len) {
+    if (isStreaming())
+      StreamedLen += Len;
+  }
+
+  void resetStreamedLen() {
+    if (isStreaming())
+      StreamedLen = 4; // The record prefix is 4 bytes long
+  }
+
   struct RecordLimit {
     uint32_t BeginOffset;
     Optional<uint32_t> MaxLength;
@@ -162,6 +234,8 @@ private:
 
   BinaryStreamReader *Reader = nullptr;
   BinaryStreamWriter *Writer = nullptr;
+  CodeViewRecordStreamer *Streamer = nullptr;
+  uint64_t StreamedLen = 0;
 };
 
 } // end namespace codeview
index b885d54..4c309c1 100644 (file)
@@ -23,9 +23,11 @@ class TypeRecordMapping : public TypeVisitorCallbacks {
 public:
   explicit TypeRecordMapping(BinaryStreamReader &Reader) : IO(Reader) {}
   explicit TypeRecordMapping(BinaryStreamWriter &Writer) : IO(Writer) {}
+  explicit TypeRecordMapping(CodeViewRecordStreamer &Streamer) : IO(Streamer) {}
 
   using TypeVisitorCallbacks::visitTypeBegin;
   Error visitTypeBegin(CVType &Record) override;
+  Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
   Error visitTypeEnd(CVType &Record) override;
 
   Error visitMemberBegin(CVMemberRecord &Record) override;
index fb0b579..169715b 100644 (file)
@@ -82,6 +82,11 @@ public:
     Pipeline.push_back(&Callbacks);
   }
 
+  void addCallbackToPipelineFront(TypeVisitorCallbacks &Callbacks) {
+    auto CallBackItr = Pipeline.begin();
+    Pipeline.insert(CallBackItr, &Callbacks);
+  }
+
 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
   Error visitKnownRecord(CVType &CVR, Name##Record &Record) override {         \
     return visitKnownRecordImpl(CVR, Record);                                  \
index 9f8ed86..61fe698 100644 (file)
@@ -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"
 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);
   }
 }
index dd6f75f..ec4773d 100644 (file)
@@ -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) {
index 92c795a..2b69a1e 100644 (file)
@@ -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()) {
index 12fb50d..104e310 100644 (file)
@@ -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;
   }
index 7bd857e..3b31f23 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=i686-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; struct S {
index 67059ee..1e1e8bc 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc -filetype=obj < %s | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; We need three continuation records for this.
 
index e832328..4635055 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 ;
 ; Command to generate function-options.ll
 ; $ clang++ class-options-common.cpp -S -emit-llvm -g -gcodeview -o class-options-common.ll
index 1dfe885..5a012ce 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc -filetype=obj < %s | llvm-readobj --codeview - | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=i686-windows | llvm-readobj --codeview - | FileCheck %s
 
 ; Objective-C++ source demonstrating the issue:
 ; void (^b)(void) = []() {};
index 3ece1fd..8b4e57a 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; Both A and B should get forward declarations and complete definitions for this
 ; example.
index 2059918..bdd4d0f 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; Command to generate enum-co.ll
 ; $ clang++ enum-co.cpp -S -emit-llvm -g -gcodeview -o enum-co.ll
index 15bbce0..6580c51 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=i686-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; Generated from the following C++ source:
 ; enum E : int { BLAH };
index 50058de..76831e7 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 ;
 ; Command to generate function-options.ll
 ; $ clang++ function-options.cpp -S -emit-llvm -g -gcodeview -o function-options.ll
index 22f3f32..a9a437d 100644 (file)
@@ -1,5 +1,6 @@
 ; RUN: llc < %s | FileCheck %s --check-prefix=ASM
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s --check-prefix=OBJ
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s --check-prefix=OBJ
 ; RUN: llc < %s -filetype=obj | obj2yaml | FileCheck %s --check-prefix=YAML
 
 ; C++ source to regenerate:
index 2e10a10..b2f487a 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj -o - | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s -o - | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; $ cat t.cpp
index 1b2d113..404ff6d 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj -o - | llvm-readobj --codeview --codeview-subsection-bytes | FileCheck %s
+; RUN: llc < %s -o - | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj --codeview --codeview-subsection-bytes | FileCheck %s
 
 ; Check how we pad out the LF_FUNC_ID records. The 00F3F2F1 bytes in LeafData are
 ; what's interesting here.
index 4bca6f7..5267b47 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc -mtriple=x86_64-windows-msvc < %s -filetype=obj -o - | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc -mtriple=x86_64-windows-msvc < %s -o - | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; We should only get one func id record, and both inlinees should point to it,
 ; even though there are two DISubprograms.
index 64e1253..981ae5a 100644 (file)
@@ -81,8 +81,6 @@
 ; ASM: #   Arguments [
 ; ASM: #   ]
 ; ASM: # }
-; ASM: .byte   0x06, 0x00, 0x01, 0x12
-; ASM: .byte   0x00, 0x00, 0x00, 0x00
 ; ASM: # Procedure (0x1001) {
 ; ASM: #   TypeLeafKind: LF_PROCEDURE (0x1008)
 ; ASM: #   ReturnType: void (0x3)
 ; ASM: #   NumParameters: 0
 ; ASM: #   ArgListType: () (0x1000)
 ; ASM: # }
-; ASM: .byte   0x0e, 0x00, 0x08, 0x10
-; ASM: .byte   0x03, 0x00, 0x00, 0x00
-; ASM: .byte   0x00, 0x00, 0x00, 0x00
-; ASM: .byte   0x00, 0x10, 0x00, 0x00
 ; ASM: # FuncId (0x1002) {
 ; ASM: #   TypeLeafKind: LF_FUNC_ID (0x1601)
 ; ASM: #   ParentScope: 0x0
 ; ASM: #   FunctionType: void () (0x1001)
 ; ASM: #   Name: bar
 ; ASM: # }
-; ASM: .byte   0x0e, 0x00, 0x01, 0x16
-; ASM: .byte   0x00, 0x00, 0x00, 0x00
-; ASM: .byte   0x01, 0x10, 0x00, 0x00
-; ASM: .byte   0x62, 0x61, 0x72, 0x00
 ; ASM: # FuncId (0x1003) {
 ; ASM: #   TypeLeafKind: LF_FUNC_ID (0x1601)
 ; ASM: #   ParentScope: 0x0
 ; ASM: #   FunctionType: void () (0x1001)
 ; ASM: #   Name: foo
 ; ASM: # }
-; ASM: .byte   0x0e, 0x00, 0x01, 0x16
-; ASM: .byte   0x00, 0x00, 0x00, 0x00
-; ASM: .byte   0x01, 0x10, 0x00, 0x00
-; ASM: .byte   0x66, 0x6f, 0x6f, 0x00
 
 ; We should only the LF_FUNC_ID records that we needed to reference.
 ; OBJ: CodeViewTypes [
index 83e8e02..45a374b 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=i686-windows | llvm-readobj - --codeview | FileCheck %s
 ;
 ; Verify lambda routines are emitted properly in CodeView.
 ;
index 93ac80a..1488e08 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc %s -o - -filetype=obj | llvm-readobj --codeview | FileCheck %s
+; RUN: llc %s -o - | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj --codeview | FileCheck %s
 
 ; CHECK: Struct (0x1000) {
 ; CHECK:   TypeLeafKind: LF_STRUCTURE (0x1505)
index 9579daf..c68e431 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; struct HasNested {
index 9e26b82..8d4253b 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; This test checks that types which are used in expressions, but for which
 ; there are no variables, known as retained types, get emitted.
index a644ea9..23509b4 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; Check that we keep namespace scopes around the same way MSVC does.
 ; We do function scopes slightly differently, but everything should be alright.
index eb19256..1e51f80 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=i686-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; Check for the appropriate MethodKind below.
 
index 605dc18..fbe7f6c 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; $ cat m.cpp
index ea10142..3aa0686 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=i686-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; $ cat t.cpp
index c9e800c..abfcbbf 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc -filetype=obj < %s | llvm-readobj --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj --codeview | FileCheck %s
 
 ; We should emit two array types: one used to describe the static data member,
 ; and the other used by the S_GDATA32 for the definition.
index 852d395..7473c83 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=i686-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; $ cat t.cpp
index 773b2a1..343615a 100644 (file)
@@ -1,4 +1,6 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | FileCheck %s --check-prefix=ASM
 
 ; C++ source to regenerate:
 ; $ cat t.cpp
 ; CHECK:   ]
 ; CHECK: ]
 
+
+
+; ASM: .section        .debug$T,"dr"
+; ASM: .p2align        2
+; ASM: .long   4                       # Debug section magic
+; ASM: .short  18
+; ASM: .short  4609
+; ASM: .long   3
+; ASM: .long   64
+; ASM: .long   65
+; ASM: .long   19
+; ASM: # ArgList (0x1000) {
+; ASM: #   TypeLeafKind: LF_ARGLIST (0x1201)
+; ASM: #   NumArgs: 3
+; ASM: #   Arguments [
+; ASM: #     ArgType: float (0x40)
+; ASM: #     ArgType: double (0x41)
+; ASM: #     ArgType: __int64 (0x13)
+; ASM: #   ]
+; ASM: # }
+; ASM: .short  14
+; ASM: .short  4104
+; ASM: .long   3
+; ASM: .byte   0
+; ASM: .byte   0
+; ASM: .short  3
+; ASM: .long   4096
+; ASM: # Procedure (0x1001) {
+; ASM: #   TypeLeafKind: LF_PROCEDURE (0x1008)
+; ASM: #   ReturnType: void (0x3)
+; ASM: #   CallingConvention: NearC (0x0)
+; ASM: #   FunctionOptions [ (0x0)
+; ASM: #   ]
+; ASM: #   NumParameters: 3
+; ASM: #   ArgListType: (float, double, __int64) (0x1000)
+; ASM: # }
+; ASM: .short  14
+; ASM: .short  5633
+; ASM: .long   0
+; ASM: .long   4097
+; ASM: .asciz  "f"
+; ASM: .byte   242
+; ASM: .byte   241
+; ASM: # FuncId (0x1002) {
+; ASM: #   TypeLeafKind: LF_FUNC_ID (0x1601)
+; ASM: #   ParentScope: 0x0
+; ASM: #   FunctionType: void (float, double, __int64) (0x1001)
+; ASM: #   Name: f
+; ASM: # }
+; ASM: .short  10
+; ASM: .short  4097
+; ASM: .long   116
+; ASM: .short  1
+; ASM: .byte   242
+; ASM: .byte   241
+; ASM: # Modifier (0x1003) {
+; ASM: #   TypeLeafKind: LF_MODIFIER (0x1001)
+; ASM: #   ModifiedType: int (0x74)
+; ASM: #   Modifiers [ (0x1)
+; ASM: #     Const (0x1)
+; ASM: #   ]
+; ASM: # }
+; ASM: .short  10
+; ASM: .short  4098
+; ASM: .long   4099
+; ASM: .long   65548
+; ASM: # Pointer (0x1004) {
+; ASM: #   TypeLeafKind: LF_POINTER (0x1002)
+; ASM: #   PointeeType: const int (0x1003)
+; ASM: #   PtrType: Near64 (0xC)
+; ASM: #   PtrMode: Pointer (0x0)
+; ASM: #   IsFlat: 0
+; ASM: #   IsConst: 0
+; ASM: #   IsVolatile: 0
+; ASM: #   IsUnaligned: 0
+; ASM: #   IsRestrict: 0
+; ASM: #   IsThisPtr&: 0
+; ASM: #   IsThisPtr&&: 0
+; ASM: #   SizeOf: 8
+; ASM: # }
+; ASM: .short  22
+; ASM: .short  5381
+; ASM: .short  0
+; ASM: .short  128
+; ASM: .long   0
+; ASM: .long   0
+; ASM: .long   0
+; ASM: .short  0
+; ASM: .asciz  "A"
+; ASM: # Struct (0x1005) {
+; ASM: #   TypeLeafKind: LF_STRUCTURE (0x1505)
+; ASM: #   MemberCount: 0
+; ASM: #   Properties [ (0x80)
+; ASM: #     ForwardReference (0x80)
+; ASM: #   ]
+; ASM: #   FieldList: 0x0
+; ASM: #   DerivedFrom: 0x0
+; ASM: #   VShape: 0x0
+; ASM: #   SizeOf: 0
+; ASM: #   Name: A
+; ASM: # }
+; ASM: .short  18
+; ASM: .short  4098
+; ASM: .long   116
+; ASM: .long   32844
+; ASM: .long   4101
+; ASM: .short  4
+; ASM: .byte   242
+; ASM: .byte   241
+; ASM: # Pointer (0x1006) {
+; ASM: #   TypeLeafKind: LF_POINTER (0x1002)
+; ASM: #   PointeeType: int (0x74)
+; ASM: #   PtrType: Near64 (0xC)
+; ASM: #   PtrMode: PointerToDataMember (0x2)
+; ASM: #   IsFlat: 0
+; ASM: #   IsConst: 0
+; ASM: #   IsVolatile: 0
+; ASM: #   IsUnaligned: 0
+; ASM: #   IsRestrict: 0
+; ASM: #   IsThisPtr&: 0
+; ASM: #   IsThisPtr&&: 0
+; ASM: #   SizeOf: 4
+; ASM: #   ClassType: A (0x1005)
+; ASM: #   Representation: GeneralData (0x4)
+; ASM: # }
+; ASM: .short  10
+; ASM: .short  4098
+; ASM: .long   4101
+; ASM: .long   66572
+; ASM: # Pointer (0x1007) {
+; ASM: #   TypeLeafKind: LF_POINTER (0x1002)
+; ASM: #   PointeeType: A (0x1005)
+; ASM: #   PtrType: Near64 (0xC)
+; ASM: #   PtrMode: Pointer (0x0)
+; ASM: #   IsFlat: 0
+; ASM: #   IsConst: 1
+; ASM: #   IsVolatile: 0
+; ASM: #   IsUnaligned: 0
+; ASM: #   IsRestrict: 0
+; ASM: #   IsThisPtr&: 0
+; ASM: #   IsThisPtr&&: 0
+; ASM: #   SizeOf: 8
+; ASM: # }
+; ASM: .short  6
+; ASM: .short  4609
+; ASM: .long   0
+; ASM: # ArgList (0x1008) {
+; ASM: #   TypeLeafKind: LF_ARGLIST (0x1201)
+; ASM: #   NumArgs: 0
+; ASM: #   Arguments [
+; ASM: #   ]
+; ASM: # }
+; ASM: .short  26
+; ASM: .short  4105
+; ASM: .long   3
+; ASM: .long   4101
+; ASM: .long   4103
+; ASM: .byte   0
+; ASM: .byte   0
+; ASM: .short  0
+; ASM: .long   4104
+; ASM: .long   0
+; ASM: # MemberFunction (0x1009) {
+; ASM: #   TypeLeafKind: LF_MFUNCTION (0x1009)
+; ASM: #   ReturnType: void (0x3)
+; ASM: #   ClassType: A (0x1005)
+; ASM: #   ThisType: A* const (0x1007)
+; ASM: #   CallingConvention: NearC (0x0)
+; ASM: #   FunctionOptions [ (0x0)
+; ASM: #   ]
+; ASM: #   NumParameters: 0
+; ASM: #   ArgListType: () (0x1008)
+; ASM: #   ThisAdjustment: 0
+; ASM: # }
+; ASM: .short  30
+; ASM: .short  4611
+; ASM: .byte   0x0d, 0x15, 0x03, 0x00
+; ASM: .byte   0x74, 0x00, 0x00, 0x00
+; ASM: .byte   0x00, 0x00, 0x61, 0x00
+; ASM: .byte   0x11, 0x15, 0x03, 0x00
+; ASM: .byte   0x09, 0x10, 0x00, 0x00
+; ASM: .byte   0x41, 0x3a, 0x3a, 0x66
+; ASM: .byte   0x00, 0xf3, 0xf2, 0xf1
+; ASM: # FieldList (0x100A) {
+; ASM: #   TypeLeafKind: LF_FIELDLIST (0x1203)
+; ASM: #   DataMember {
+; ASM: #     TypeLeafKind: LF_MEMBER (0x150D)
+; ASM: #     AccessSpecifier: Public (0x3)
+; ASM: #     Type: int (0x74)
+; ASM: #     FieldOffset: 0x0
+; ASM: #     Name: a
+; ASM: #   }
+; ASM: #   OneMethod {
+; ASM: #     TypeLeafKind: LF_ONEMETHOD (0x1511)
+; ASM: #     AccessSpecifier: Public (0x3)
+; ASM: #     Type: void A::() (0x1009)
+; ASM: #     Name: A::f
+; ASM: #   }
+; ASM: # }
+; ASM: .short  22
+; ASM: .short  5381
+; ASM: .short  2
+; ASM: .short  0
+; ASM: .long   4106
+; ASM: .long   0
+; ASM: .long   0
+; ASM: .short  4
+; ASM: .asciz  "A"
+; ASM: # Struct (0x100B) {
+; ASM: #   TypeLeafKind: LF_STRUCTURE (0x1505)
+; ASM: #   MemberCount: 2
+; ASM: #   Properties [ (0x0)
+; ASM: #   ]
+; ASM: #   FieldList: <field list> (0x100A)
+; ASM: #   DerivedFrom: 0x0
+; ASM: #   VShape: 0x0
+; ASM: #   SizeOf: 4
+; ASM: #   Name: A
+; ASM: # }
+; ASM: .short  30
+; ASM: .short  5637
+; ASM: .long   0
+; ASM: .asciz  "D:\\src\\llvm\\build\\t.cpp"
+; ASM: # StringId (0x100C) {
+; ASM: #   TypeLeafKind: LF_STRING_ID (0x1605)
+; ASM: #   Id: 0x0
+; ASM: #   StringData: D:\src\llvm\build\t.cpp
+; ASM: # }
+; ASM: .short  14
+; ASM: .short  5638
+; ASM: .long   4107
+; ASM: .long   4108
+; ASM: .long   1
+; ASM: # UdtSourceLine (0x100D) {
+; ASM: #   TypeLeafKind: LF_UDT_SRC_LINE (0x1606)
+; ASM: #   UDT: A (0x100B)
+; ASM: #   SourceFile: D:\src\llvm\build\t.cpp (0x100C)
+; ASM: #   LineNumber: 1
+; ASM: # }
+; ASM: .short  18
+; ASM: .short  4098
+; ASM: .long   4105
+; ASM: .long   65644
+; ASM: .long   4101
+; ASM: .short  8
+; ASM: .byte   242
+; ASM: .byte   241
+; ASM: # Pointer (0x100E) {
+; ASM: #   TypeLeafKind: LF_POINTER (0x1002)
+; ASM: #   PointeeType: void A::() (0x1009)
+; ASM: #   PtrType: Near64 (0xC)
+; ASM: #   PtrMode: PointerToMemberFunction (0x3)
+; ASM: #   IsFlat: 0
+; ASM: #   IsConst: 0
+; ASM: #   IsVolatile: 0
+; ASM: #   IsUnaligned: 0
+; ASM: #   IsRestrict: 0
+; ASM: #   IsThisPtr&: 0
+; ASM: #   IsThisPtr&&: 0
+; ASM: #   SizeOf: 8
+; ASM: #   ClassType: A (0x1005)
+; ASM: #   Representation: GeneralFunction (0x8)
+; ASM: # }
+; ASM: .short  10
+; ASM: .short  4097
+; ASM: .long   3
+; ASM: .short  1
+; ASM: .byte   242
+; ASM: .byte   241
+; ASM: # Modifier (0x100F) {
+; ASM: #   TypeLeafKind: LF_MODIFIER (0x1001)
+; ASM: #   ModifiedType: void (0x3)
+; ASM: #   Modifiers [ (0x1)
+; ASM: #     Const (0x1)
+; ASM: #   ]
+; ASM: # }
+; ASM: .short  10
+; ASM: .short  4098
+; ASM: .long   4111
+; ASM: .long   65548
+; ASM: # Pointer (0x1010) {
+; ASM: #   TypeLeafKind: LF_POINTER (0x1002)
+; ASM: #   PointeeType: const void (0x100F)
+; ASM: #   PtrType: Near64 (0xC)
+; ASM: #   PtrMode: Pointer (0x0)
+; ASM: #   IsFlat: 0
+; ASM: #   IsConst: 0
+; ASM: #   IsVolatile: 0
+; ASM: #   IsUnaligned: 0
+; ASM: #   IsRestrict: 0
+; ASM: #   IsThisPtr&: 0
+; ASM: #   IsThisPtr&&: 0
+; ASM: #   SizeOf: 8
+; ASM: # }
+; ASM: .short  14
+; ASM: .short  4104
+; ASM: .long   3
+; ASM: .byte   0
+; ASM: .byte   0
+; ASM: .short  0
+; ASM: .long   4104
+; ASM: # Procedure (0x1011) {
+; ASM: #   TypeLeafKind: LF_PROCEDURE (0x1008)
+; ASM: #   ReturnType: void (0x3)
+; ASM: #   CallingConvention: NearC (0x0)
+; ASM: #   FunctionOptions [ (0x0)
+; ASM: #   ]
+; ASM: #   NumParameters: 0
+; ASM: #   ArgListType: () (0x1008)
+; ASM: # }
+; ASM: .short  22
+; ASM: .short  5633
+; ASM: .long   0
+; ASM: .long   4113
+; ASM: .asciz  "CharTypes"
+; ASM: .byte   242
+; ASM: .byte   241
+; ASM: # FuncId (0x1012) {
+; ASM: #   TypeLeafKind: LF_FUNC_ID (0x1601)
+; ASM: #   ParentScope: 0x0
+; ASM: #   FunctionType: void () (0x1011)
+; ASM: #   Name: CharTypes
+; ASM: # }
+; ASM: .short  26
+; ASM: .short  5637
+; ASM: .long   0
+; ASM: .asciz  "D:\\src\\llvm\\build"
+; ASM: .byte   242
+; ASM: .byte   241
+; ASM: # StringId (0x1013) {
+; ASM: #   TypeLeafKind: LF_STRING_ID (0x1605)
+; ASM: #   Id: 0x0
+; ASM: #   StringData: D:\src\llvm\build
+; ASM: # }
+; ASM: .short  14
+; ASM: .short  5637
+; ASM: .long   0
+; ASM: .asciz  "t.cpp"
+; ASM: .byte   242
+; ASM: .byte   241
+; ASM: # StringId (0x1014) {
+; ASM: #   TypeLeafKind: LF_STRING_ID (0x1605)
+; ASM: #   Id: 0x0
+; ASM: #   StringData: t.cpp
+; ASM: # }
+; ASM: .short  26
+; ASM: .short  5635
+; ASM: .short  5
+; ASM: .long   4115
+; ASM: .long   0
+; ASM: .long   4116
+; ASM: .long   0
+; ASM: .long   0
+; ASM: .byte   242
+; ASM: .byte   241
+; ASM: # BuildInfo (0x1015) {
+; ASM: #   TypeLeafKind: LF_BUILDINFO (0x1603)
+; ASM: #   NumArgs: 5
+; ASM: #   Arguments [
+; ASM: #     ArgType: D:\src\llvm\build (0x1013)
+; ASM: #     ArgType: 0x0
+; ASM: #     ArgType: t.cpp (0x1014)
+; ASM: #     ArgType: 0x0
+; ASM: #     ArgType: 0x0
+; ASM: #   ]
+; ASM: # }
+
 ; ModuleID = 't.cpp'
 source_filename = "t.cpp"
 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
index f0a4fe1..0adac00 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj -o - | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s -o - | llvm-mc -filetype=obj --triple=i386-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; $ cat t.cpp
index 88b59e4..80b1252 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; $ cat t.cpp
index d8cff6b..842df34 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; $ cat t.cpp
index 003b9c8..4cbe0a1 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; ModuleID = 'foo.3a1fbbbh-cgu.0'
 source_filename = "foo.3a1fbbbh-cgu.0"
index cf47817..64033f5 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; struct A {
index 0893db7..4110329 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; $ cat hello.cpp
index dfe1589..bc789d5 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=i686-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; $ cat t.cpp
index 33b536a..d565fee 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; $ cat t.cpp
index 34ca2b1..cdefec3 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; This test ensures that circular type references through pointer types don't
 ; cause infinite recursion. It also tests that we always refer to the forward
index c845785..5c21d05 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 ;
 ; Verify CodeView emission does not emit forward references for unnamed
 ; structs/unions.  If a forward reference is emitted for an unnamed composite
index 250ee28..4acacb3 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source to regenerate:
 ; struct A {
index ea478d8..f753326 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; Check for the appropriate MethodKind below.
 
index f2e68c5..f429f03 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; C++ source used to generate IR:
 ; $ cat t.cpp
index 2b5e25b..2c9d2b7 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -filetype=obj -o - | llvm-readobj - --codeview | FileCheck %s
+; RUN: llc < %s -o - | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s
 
 ; We used to crash on this input because UnicodeString is a forward declaration
 ; with no size. Our array type logic wanted to assert the size of the elements