[llvm] r341029 - [XRay] FDRTraceWriter and FDR Trace Loading

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 31 09:02:06 PDT 2018


Hi Dean,

Unfortunately it looks like the tests are still failing after your change. Can you take a look?

http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/19534/steps/test/logs/stdio

FAIL: LLVM-Unit :: XRay/./XRayTests.exe/FDRTraceWriterTest.WriteToStringBufferVersion1 (3122 of 43583)
******************** TEST 'LLVM-Unit :: XRay/./XRayTests.exe/FDRTraceWriterTest.WriteToStringBufferVersion1' FAILED ********************
Note: Google Test filter = FDRTraceWriterTest.WriteToStringBufferVersion1

[==========] Running 1 test from 1 test case.

[----------] Global test environment set-up.

[----------] 1 test from FDRTraceWriterTest

[ RUN      ] FDRTraceWriterTest.WriteToStringBufferVersion1

C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.src\unittests\XRay\FDRTraceWriterTest.cpp(160): error: Value of: Data.size()

Expected: is equal to 4128

  Actual: 4136

[  FAILED  ] FDRTraceWriterTest.WriteToStringBufferVersion1 (0 ms)

[----------] 1 test from FDRTraceWriterTest (0 ms total)



[----------] Global test environment tear-down

[==========] 1 test from 1 test case ran. (0 ms total)

[  PASSED  ] 0 tests.

[  FAILED  ] 1 test, listed below:

[  FAILED  ] FDRTraceWriterTest.WriteToStringBufferVersion1



 1 FAILED TEST


********************

FAIL: LLVM-Unit :: XRay/./XRayTests.exe/FDRTraceWriterTest.WriteToStringBufferVersion2 (3246 of 43583)
******************** TEST 'LLVM-Unit :: XRay/./XRayTests.exe/FDRTraceWriterTest.WriteToStringBufferVersion2' FAILED ********************
Note: Google Test filter = FDRTraceWriterTest.WriteToStringBufferVersion2

[==========] Running 1 test from 1 test case.

[----------] Global test environment set-up.

[----------] 1 test from FDRTraceWriterTest

[ RUN      ] FDRTraceWriterTest.WriteToStringBufferVersion2

C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.src\unittests\XRay\FDRTraceWriterTest.cpp(106): error: Failed

Malformed log: Read New Buffer record kind out of sequence; expected: FUNCTION_SEQUENCE at offset 105.

Program aborted due to an unhandled Error:

Malformed log: Read New Buffer record kind out of sequence; expected: FUNCTION_SEQUENCE at offset 105.LLVMSymbolizer: error reading file: PDB Error: Unable to load PDB.  Make sure the file exists and is readable.  Calling loadDataForExe



LLVMSymbolizer: error reading file: PDB Error: Unable to load PDB.  Make sure the file exists and is readable.  Calling loadDataForExe



#0 0x0115f237 (C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.obj\unittests\XRay\XRayTests.exe+0x3f237)

#1 0x759e2722 (C:\WINDOWS\System32\ucrtbase.dll+0xa2722)

#2 0x0114ff98 (C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.obj\unittests\XRay\XRayTests.exe+0x2ff98)

#3 0x0117dee0 (C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.obj\unittests\XRay\XRayTests.exe+0x5dee0)

#4 0x01190a94 (C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.obj\unittests\XRay\XRayTests.exe+0x70a94)

#5 0x00dc48d0

#6 0x65636172

#7 0x74697257 (C:\WINDOWS\System32\msvcp_win.dll+0x37257)

#8 0x65547265


********************
FAIL: LLVM-Unit :: XRay/./XRayTests.exe/FDRTraceWriterTest.WriteToStringBufferVersion3 (3247 of 43583)
******************** TEST 'LLVM-Unit :: XRay/./XRayTests.exe/FDRTraceWriterTest.WriteToStringBufferVersion3' FAILED ********************
Note: Google Test filter = FDRTraceWriterTest.WriteToStringBufferVersion3

[==========] Running 1 test from 1 test case.

[----------] Global test environment set-up.

[----------] 1 test from FDRTraceWriterTest

[ RUN      ] FDRTraceWriterTest.WriteToStringBufferVersion3

C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.src\unittests\XRay\FDRTraceWriterTest.cpp(62): error: Failed

Malformed log: Read New Buffer record kind out of sequence; expected: FUNCTION_SEQUENCE at offset 121.

Program aborted due to an unhandled Error:

Malformed log: Read New Buffer record kind out of sequence; expected: FUNCTION_SEQUENCE at offset 121.LLVMSymbolizer: error reading file: PDB Error: Unable to load PDB.  Make sure the file exists and is readable.  Calling loadDataForExe



LLVMSymbolizer: error reading file: PDB Error: Unable to load PDB.  Make sure the file exists and is readable.  Calling loadDataForExe



#0 0x0115f237 (C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.obj\unittests\XRay\XRayTests.exe+0x3f237)

#1 0x759e2722 (C:\WINDOWS\System32\ucrtbase.dll+0xa2722)

#2 0x0114ff98 (C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.obj\unittests\XRay\XRayTests.exe+0x2ff98)

#3 0x0117dee0 (C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.obj\unittests\XRay\XRayTests.exe+0x5dee0)

#4 0x01190a94 (C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.obj\unittests\XRay\XRayTests.exe+0x70a94)

#5 0x0127c970

#6 0x65636172

#7 0x74697257 (C:\WINDOWS\System32\msvcp_win.dll+0x37257)

#8 0x65547265

#9 0x73007473

#10 0x00392f74


********************

Douglas Yung

> -----Original Message-----
> From: Dean Michael Berris [mailto:dean.berris at gmail.com]
> Sent: Friday, August 31, 2018 3:42
> To: Yung, Douglas
> Cc: Dean Michael Berris; Vedant Kumar via llvm-commits
> Subject: Re: [llvm] r341029 - [XRay] FDRTraceWriter and FDR Trace
> Loading
> 
> This should now be fixed in r341194.
> 
> Thanks Doug!
> 
> > On 31 Aug 2018, at 20:01, Dean Michael Berris <dean.berris at gmail.com>
> wrote:
> >
> > Actually, I think I found it — it seems that I’m relying on bitfield
> order being portable, but it isn’t. I’m working on a fix now.
> >
> >> On 31 Aug 2018, at 19:37, Dean Michael Berris
> <dean.berris at gmail.com> wrote:
> >>
> >> Oops, thanks for pointing it out.
> >>
> >> Is there a way to make this XFAIL on Windows?
> >>
> >> This is really bizarre, since I don’t have a way of reproducing
> this.
> >>
> >>> On 31 Aug 2018, at 18:37, via llvm-commits <llvm-
> commits at lists.llvm.org> wrote:
> >>>
> >>> Hi Dean,
> >>>
> >>> The unit test you added in this commit, FDRTraceWriterTest is
> causing 3 failures on the PS4 Windows bot, can you take a look?
> >>>
> >>> http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-
> windows10pro-fast/builds/19491/steps/test/logs/stdio
> >>>
> >>> Failing Tests (3):
> >>>  LLVM-Unit ::
> XRay/./XRayTests.exe/FDRTraceWriterTest.WriteToStringBufferVersion1
> >>>  LLVM-Unit ::
> XRay/./XRayTests.exe/FDRTraceWriterTest.WriteToStringBufferVersion2
> >>>  LLVM-Unit ::
> XRay/./XRayTests.exe/FDRTraceWriterTest.WriteToStringBufferVersion3
> >>>
> >>> Sample failure output:
> >>>
> >>> FAIL: LLVM-Unit ::
> XRay/./XRayTests.exe/FDRTraceWriterTest.WriteToStringBufferVersion1
> (3227 of 43541)
> >>> ******************** TEST 'LLVM-Unit ::
> XRay/./XRayTests.exe/FDRTraceWriterTest.WriteToStringBufferVersion1'
> FAILED ********************
> >>> Note: Google Test filter =
> FDRTraceWriterTest.WriteToStringBufferVersion1
> >>>
> >>> [==========] Running 1 test from 1 test case.
> >>>
> >>> [----------] Global test environment set-up.
> >>>
> >>> [----------] 1 test from FDRTraceWriterTest
> >>>
> >>> [ RUN      ] FDRTraceWriterTest.WriteToStringBufferVersion1
> >>>
> >>> C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-
> fast\llvm.src\unittests\XRay\FDRTraceWriterTest.cpp(157): error: Failed
> >>>
> >>> Malformed log: Read New Buffer record kind out of sequence;
> expected: FUNCTION_SEQUENCE at offset 89.
> >>>
> >>> Program aborted due to an unhandled Error:
> >>>
> >>> Malformed log: Read New Buffer record kind out of sequence;
> expected: FUNCTION_SEQUENCE at offset 89.LLVMSymbolizer: error reading
> file: PDB Error: Unable to load PDB.  Make sure the file exists and is
> readable.  Calling loadDataForExe
> >>>
> >>>
> >>>
> >>> LLVMSymbolizer: error reading file: PDB Error: Unable to load PDB.
> Make sure the file exists and is readable.  Calling loadDataForExe
> >>>
> >>>
> >>>
> >>> #0 0x0003e887 (C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-
> windows10pro-fast\llvm.obj\unittests\XRay\XRayTests.exe+0x2e887)
> >>>
> >>> #1 0x759e2722 (C:\WINDOWS\System32\ucrtbase.dll+0xa2722)
> >>>
> >>> #2 0x0003b918 (C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-
> windows10pro-fast\llvm.obj\unittests\XRay\XRayTests.exe+0x2b918)
> >>>
> >>> #3 0x00064880 (C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-
> windows10pro-fast\llvm.obj\unittests\XRay\XRayTests.exe+0x54880)
> >>>
> >>> #4 0x00076b54 (C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-
> windows10pro-fast\llvm.obj\unittests\XRay\XRayTests.exe+0x66b54)
> >>>
> >>> #5 0x01b10518
> >>>
> >>> #6 0x65636172
> >>>
> >>> #7 0x74697257 (C:\WINDOWS\System32\msvcp_win.dll+0x37257)
> >>>
> >>> #8 0x65547265
> >>>
> >>>
> >>> ********************
> >>>
> >>> Douglas Yung
> >>>
> >>>> -----Original Message-----
> >>>> From: llvm-commits [mailto:llvm-commits-bounces at lists.llvm.org] On
> >>>> Behalf Of Dean Michael Berris via llvm-commits
> >>>> Sent: Thursday, August 30, 2018 0:22
> >>>> To: llvm-commits at lists.llvm.org
> >>>> Subject: [llvm] r341029 - [XRay] FDRTraceWriter and FDR Trace
> Loading
> >>>>
> >>>> Author: dberris
> >>>> Date: Thu Aug 30 00:22:21 2018
> >>>> New Revision: 341029
> >>>>
> >>>> URL: http://llvm.org/viewvc/llvm-project?rev=341029&view=rev
> >>>> Log:
> >>>> [XRay] FDRTraceWriter and FDR Trace Loading
> >>>>
> >>>> Summary:
> >>>> This is the first step in the larger refactoring and reduction of
> >>>> D50441.
> >>>>
> >>>> This step in the process does the following:
> >>>>
> >>>> - Introduces more granular types of `Record`s representing the
> many
> >>>> kinds of records written/read by the Flight Data Recorder (FDR)
> mode
> >>>> `Trace` loading function(s).
> >>>>
> >>>> - Introduces an abstract `RecordVisitor` type meant to handle the
> >>>> processing of the various `Record` derived types. This
> >>>> `RecordVisitor`
> >>>> has two implementations in this patch: `RecordInitializer` and
> >>>> `FDRTraceWriter`.
> >>>>
> >>>> - We also introduce a convenience interface for building a
> collection
> >>>> of
> >>>> `Record` instances called a `LogBuilder`. This allows us to
> generate
> >>>> sequences of `Record` instances manually (used in unit tests but
> >>>> useful otherwise).
> >>>>
> >>>> - The`FDRTraceWriter` class implements the `RecordVisitor`
> interface
> >>>> and
> >>>> handles the writing of metadata records to a `raw_ostream`. We
> >>>> demonstrate that in the unit test, we can generate in-memory FDR
> mode
> >>>> traces using the specific `Record` derived types, which we load
> >>>> through the `loadTrace(...)` function yielding valid `Trace`
> objects.
> >>>>
> >>>> This patch introduces the required types and concepts for us to
> start
> >>>> replacing the logic implemented in the `loadFDRLog` function to
> use the
> >>>> more granular types. In subsequent patches, we will introduce more
> >>>> visitor implementations which isolate the verification, printing,
> >>>> indexing, production/consumption, and finally the conversion of
> the FDR
> >>>> mode logs.
> >>>>
> >>>> The overarching goal of these changes is to make handling FDR mode
> logs
> >>>> better tested, more understandable, more extensible, and more
> >>>> systematic. This will also allow us to better represent the
> execution
> >>>> trace, as we improve the fidelity of the events we represent in an
> XRay
> >>>> `Trace` object, which we intend to do after FDR mode log
> processing is
> >>>> in better shape.
> >>>>
> >>>> Reviewers: eizan
> >>>>
> >>>> Reviewed By: eizan
> >>>>
> >>>> Subscribers: mgorny, hiraditya, llvm-commits
> >>>>
> >>>> Differential Revision: https://reviews.llvm.org/D51210
> >>>>
> >>>> Added:
> >>>>  llvm/trunk/include/llvm/XRay/FDRLogBuilder.h
> >>>>  llvm/trunk/include/llvm/XRay/FDRRecords.h
> >>>>  llvm/trunk/include/llvm/XRay/FDRTraceWriter.h
> >>>>  llvm/trunk/lib/XRay/FDRRecords.cpp
> >>>>  llvm/trunk/lib/XRay/FDRTraceWriter.cpp
> >>>>  llvm/trunk/lib/XRay/RecordInitializer.cpp
> >>>>  llvm/trunk/unittests/XRay/FDRTraceWriterTest.cpp
> >>>> Modified:
> >>>>  llvm/trunk/lib/XRay/CMakeLists.txt
> >>>>  llvm/trunk/unittests/XRay/CMakeLists.txt
> >>>>
> >>>> Added: llvm/trunk/include/llvm/XRay/FDRLogBuilder.h
> >>>> URL: http://llvm.org/viewvc/llvm-
> >>>>
> project/llvm/trunk/include/llvm/XRay/FDRLogBuilder.h?rev=341029&view=au
> >>>> to
> >>>>
> =======================================================================
> >>>> =======
> >>>> --- llvm/trunk/include/llvm/XRay/FDRLogBuilder.h (added)
> >>>> +++ llvm/trunk/include/llvm/XRay/FDRLogBuilder.h Thu Aug 30
> 00:22:21
> >>>> 2018
> >>>> @@ -0,0 +1,41 @@
> >>>> +//===- FDRLogBuilder.h - XRay FDR Log Building Utility ----------
> -----
> >>>> -----===//
> >>>> +//
> >>>> +//                     The LLVM Compiler Infrastructure
> >>>> +//
> >>>> +// This file is distributed under the University of Illinois Open
> >>>> Source
> >>>> +// License. See LICENSE.TXT for details.
> >>>> +//
> >>>> +//===------------------------------------------------------------
> -----
> >>>> -----===//
> >>>> +#ifndef LLVM_INCLUDE_LLVM_XRAY_FDRLOGBUILDER_H_
> >>>> +#define LLVM_INCLUDE_LLVM_XRAY_FDRLOGBUILDER_H_
> >>>> +
> >>>> +#include "llvm/XRay/FDRRecords.h"
> >>>> +
> >>>> +namespace llvm {
> >>>> +namespace xray {
> >>>> +
> >>>> +/// The LogBuilder class allows for creating ad-hoc collections
> of
> >>>> records
> >>>> +/// through the `add<...>(...)` function. An example use of this
> API
> >>>> is in
> >>>> +/// crafting arbitrary sequences of records:
> >>>> +///
> >>>> +///   auto Records = LogBuilder()
> >>>> +///       .add<BufferExtents>(256)
> >>>> +///       .add<NewBufferRecord>(1)
> >>>> +///       .consume();
> >>>> +///
> >>>> +class LogBuilder {
> >>>> +  std::vector<std::unique_ptr<Record>> Records;
> >>>> +
> >>>> +public:
> >>>> +  template <class R, class... T> LogBuilder &add(T &&... A) {
> >>>> +    Records.emplace_back(new R(std::forward<T>(A)...));
> >>>> +    return *this;
> >>>> +  }
> >>>> +
> >>>> +  std::vector<std::unique_ptr<Record>> consume() { return
> >>>> std::move(Records); }
> >>>> +};
> >>>> +
> >>>> +} // namespace xray
> >>>> +} // namespace llvm
> >>>> +
> >>>> +#endif // LLVM_INCLUDE_LLVM_XRAY_FDRLOGBUILDER_H_
> >>>>
> >>>> Added: llvm/trunk/include/llvm/XRay/FDRRecords.h
> >>>> URL: http://llvm.org/viewvc/llvm-
> >>>>
> project/llvm/trunk/include/llvm/XRay/FDRRecords.h?rev=341029&view=auto
> >>>>
> =======================================================================
> >>>> =======
> >>>> --- llvm/trunk/include/llvm/XRay/FDRRecords.h (added)
> >>>> +++ llvm/trunk/include/llvm/XRay/FDRRecords.h Thu Aug 30 00:22:21
> 2018
> >>>> @@ -0,0 +1,292 @@
> >>>> +//===- FDRRecords.h - XRay Flight Data Recorder Mode Records ----
> -----
> >>>> -----===//
> >>>> +//
> >>>> +//                     The LLVM Compiler Infrastructure
> >>>> +//
> >>>> +// This file is distributed under the University of Illinois Open
> >>>> Source
> >>>> +// License. See LICENSE.TXT for details.
> >>>> +//
> >>>> +//===------------------------------------------------------------
> -----
> >>>> -----===//
> >>>> +//
> >>>> +// Define types and operations on these types that represent the
> >>>> different kinds
> >>>> +// of records we encounter in XRay flight data recorder mode
> traces.
> >>>> +//
> >>>> +//===------------------------------------------------------------
> -----
> >>>> -----===//
> >>>> +#ifndef LLVM_LIB_XRAY_FDRRECORDS_H_
> >>>> +#define LLVM_LIB_XRAY_FDRRECORDS_H_
> >>>> +
> >>>> +#include "llvm/Support/DataExtractor.h"
> >>>> +#include "llvm/Support/Error.h"
> >>>> +#include "llvm/XRay/XRayRecord.h"
> >>>> +#include <cstdint>
> >>>> +
> >>>> +namespace llvm {
> >>>> +namespace xray {
> >>>> +
> >>>> +class RecordVisitor;
> >>>> +class RecordInitializer;
> >>>> +
> >>>> +class Record {
> >>>> +protected:
> >>>> +  enum class Type {
> >>>> +    Unknown,
> >>>> +    Function,
> >>>> +    Metadata,
> >>>> +  };
> >>>> +
> >>>> +public:
> >>>> +  Record(const Record &) = delete;
> >>>> +  Record(Record &&) = delete;
> >>>> +  Record &operator=(const Record &) = delete;
> >>>> +  Record &operator=(Record &&) = delete;
> >>>> +  Record() = default;
> >>>> +
> >>>> +  virtual Type type() const = 0;
> >>>> +
> >>>> +  // Each Record should be able to apply an abstract visitor, and
> >>>> choose the
> >>>> +  // appropriate function in the visitor to invoke, given its own
> >>>> type.
> >>>> +  virtual Error apply(RecordVisitor &V) = 0;
> >>>> +
> >>>> +  virtual ~Record() = default;
> >>>> +};
> >>>> +
> >>>> +class MetadataRecord : public Record {
> >>>> +protected:
> >>>> +  static constexpr int kMetadataBodySize = 15;
> >>>> +  friend class RecordInitializer;
> >>>> +
> >>>> +public:
> >>>> +  enum class MetadataType : unsigned {
> >>>> +    Unknown,
> >>>> +    BufferExtents,
> >>>> +    WallClockTime,
> >>>> +    NewCPUId,
> >>>> +    TSCWrap,
> >>>> +    CustomEvent,
> >>>> +    CallArg,
> >>>> +    PIDEntry,
> >>>> +    NewBuffer,
> >>>> +    EndOfBuffer,
> >>>> +  };
> >>>> +
> >>>> +  Type type() const override { return Type::Metadata; }
> >>>> +
> >>>> +  // All metadata records must know to provide the type of their
> open
> >>>> +  // metadata record.
> >>>> +  virtual MetadataType metadataType() const = 0;
> >>>> +
> >>>> +  virtual ~MetadataRecord() = default;
> >>>> +};
> >>>> +
> >>>> +// What follows are specific Metadata record types which
> encapsulate
> >>>> the
> >>>> +// information associated with specific metadata record types in
> an
> >>>> FDR mode
> >>>> +// log.
> >>>> +class BufferExtents : public MetadataRecord {
> >>>> +  uint64_t Size = 0;
> >>>> +  friend class RecordInitializer;
> >>>> +
> >>>> +public:
> >>>> +  BufferExtents() = default;
> >>>> +  explicit BufferExtents(uint64_t S) : MetadataRecord(), Size(S)
> {}
> >>>> +
> >>>> +  MetadataType metadataType() const override {
> >>>> +    return MetadataType::BufferExtents;
> >>>> +  }
> >>>> +
> >>>> +  uint64_t size() const { return Size; }
> >>>> +
> >>>> +  Error apply(RecordVisitor &V) override;
> >>>> +};
> >>>> +
> >>>> +class WallclockRecord : public MetadataRecord {
> >>>> +  uint64_t Seconds = 0;
> >>>> +  uint32_t Nanos = 0;
> >>>> +  friend class RecordInitializer;
> >>>> +
> >>>> +public:
> >>>> +  WallclockRecord() = default;
> >>>> +  explicit WallclockRecord(uint64_t S, uint32_t N)
> >>>> +      : MetadataRecord(), Seconds(S), Nanos(N) {}
> >>>> +
> >>>> +  MetadataType metadataType() const override {
> >>>> +    return MetadataType::WallClockTime;
> >>>> +  }
> >>>> +
> >>>> +  uint64_t seconds() const { return Seconds; }
> >>>> +  uint32_t nanos() const { return Nanos; }
> >>>> +
> >>>> +  Error apply(RecordVisitor &V) override;
> >>>> +};
> >>>> +
> >>>> +class NewCPUIDRecord : public MetadataRecord {
> >>>> +  uint16_t CPUId = 0;
> >>>> +  friend class RecordInitializer;
> >>>> +
> >>>> +public:
> >>>> +  NewCPUIDRecord() = default;
> >>>> +  explicit NewCPUIDRecord(uint16_t C) : MetadataRecord(),
> CPUId(C) {}
> >>>> +
> >>>> +  MetadataType metadataType() const override { return
> >>>> MetadataType::NewCPUId; }
> >>>> +
> >>>> +  uint16_t cpuid() const { return CPUId; }
> >>>> +
> >>>> +  Error apply(RecordVisitor &V) override;
> >>>> +};
> >>>> +
> >>>> +class TSCWrapRecord : public MetadataRecord {
> >>>> +  uint64_t BaseTSC = 0;
> >>>> +  friend class RecordInitializer;
> >>>> +
> >>>> +public:
> >>>> +  TSCWrapRecord() = default;
> >>>> +  explicit TSCWrapRecord(uint64_t B) : MetadataRecord(),
> BaseTSC(B) {}
> >>>> +
> >>>> +  MetadataType metadataType() const override { return
> >>>> MetadataType::TSCWrap; }
> >>>> +
> >>>> +  uint64_t tsc() const { return BaseTSC; }
> >>>> +
> >>>> +  Error apply(RecordVisitor &V) override;
> >>>> +};
> >>>> +
> >>>> +class CustomEventRecord : public MetadataRecord {
> >>>> +  int32_t Size = 0;
> >>>> +  uint64_t TSC = 0;
> >>>> +  std::string Data{};
> >>>> +  friend class RecordInitializer;
> >>>> +
> >>>> +public:
> >>>> +  CustomEventRecord() = default;
> >>>> +  explicit CustomEventRecord(uint64_t S, uint64_t T, std::string
> D)
> >>>> +      : MetadataRecord(), Size(S), TSC(T), Data(std::move(D)) {}
> >>>> +
> >>>> +  MetadataType metadataType() const override {
> >>>> +    return MetadataType::CustomEvent;
> >>>> +  }
> >>>> +
> >>>> +  int32_t size() const { return Size; }
> >>>> +  uint64_t tsc() const { return TSC; }
> >>>> +  StringRef data() const { return Data; }
> >>>> +
> >>>> +  Error apply(RecordVisitor &V) override;
> >>>> +};
> >>>> +
> >>>> +class CallArgRecord : public MetadataRecord {
> >>>> +  uint64_t Arg;
> >>>> +  friend class RecordInitializer;
> >>>> +
> >>>> +public:
> >>>> +  CallArgRecord() = default;
> >>>> +  explicit CallArgRecord(uint64_t A) : MetadataRecord(), Arg(A)
> {}
> >>>> +
> >>>> +  MetadataType metadataType() const override { return
> >>>> MetadataType::CallArg; }
> >>>> +
> >>>> +  uint64_t arg() const { return Arg; }
> >>>> +
> >>>> +  Error apply(RecordVisitor &V) override;
> >>>> +};
> >>>> +
> >>>> +class PIDRecord : public MetadataRecord {
> >>>> +  uint64_t PID = 0;
> >>>> +  friend class RecordInitializer;
> >>>> +
> >>>> +public:
> >>>> +  PIDRecord() = default;
> >>>> +  explicit PIDRecord(uint64_t P) : MetadataRecord(), PID(P) {}
> >>>> +
> >>>> +  MetadataType metadataType() const override { return
> >>>> MetadataType::PIDEntry; }
> >>>> +
> >>>> +  uint64_t pid() const { return PID; }
> >>>> +
> >>>> +  Error apply(RecordVisitor &V) override;
> >>>> +};
> >>>> +
> >>>> +class NewBufferRecord : public MetadataRecord {
> >>>> +  int32_t TID = 0;
> >>>> +  friend class RecordInitializer;
> >>>> +
> >>>> +public:
> >>>> +  NewBufferRecord() = default;
> >>>> +  explicit NewBufferRecord(int32_t T) : MetadataRecord(), TID(T)
> {}
> >>>> +
> >>>> +  MetadataType metadataType() const override { return
> >>>> MetadataType::NewBuffer; }
> >>>> +
> >>>> +  int32_t tid() const { return TID; }
> >>>> +
> >>>> +  Error apply(RecordVisitor &V) override;
> >>>> +};
> >>>> +
> >>>> +class EndBufferRecord : public MetadataRecord {
> >>>> +public:
> >>>> +  EndBufferRecord() = default;
> >>>> +
> >>>> +  MetadataType metadataType() const override {
> >>>> +    return MetadataType::EndOfBuffer;
> >>>> +  }
> >>>> +
> >>>> +  Error apply(RecordVisitor &V) override;
> >>>> +};
> >>>> +
> >>>> +class FunctionRecord : public Record {
> >>>> +  RecordTypes Kind;
> >>>> +  int32_t FuncId;
> >>>> +  uint32_t Delta;
> >>>> +  friend class RecordInitializer;
> >>>> +
> >>>> +  static constexpr unsigned kFunctionRecordSize = 8;
> >>>> +
> >>>> +public:
> >>>> +  FunctionRecord() = default;
> >>>> +  explicit FunctionRecord(RecordTypes K, int32_t F, uint32_t D)
> >>>> +      : Record(), Kind(K), FuncId(F), Delta(D) {}
> >>>> +
> >>>> +  Type type() const override { return Type::Function; }
> >>>> +
> >>>> +  // A function record is a concrete record type which has a
> number of
> >>>> common
> >>>> +  // properties.
> >>>> +  RecordTypes recordType() const { return Kind; }
> >>>> +  int32_t functionId() const { return FuncId; }
> >>>> +  uint64_t delta() const { return Delta; }
> >>>> +
> >>>> +  Error apply(RecordVisitor &V) override;
> >>>> +};
> >>>> +
> >>>> +class RecordVisitor {
> >>>> +public:
> >>>> +  virtual ~RecordVisitor() = default;
> >>>> +
> >>>> +  // Support all specific kinds of records:
> >>>> +  virtual Error visit(BufferExtents &) = 0;
> >>>> +  virtual Error visit(WallclockRecord &) = 0;
> >>>> +  virtual Error visit(NewCPUIDRecord &) = 0;
> >>>> +  virtual Error visit(TSCWrapRecord &) = 0;
> >>>> +  virtual Error visit(CustomEventRecord &) = 0;
> >>>> +  virtual Error visit(CallArgRecord &) = 0;
> >>>> +  virtual Error visit(PIDRecord &) = 0;
> >>>> +  virtual Error visit(NewBufferRecord &) = 0;
> >>>> +  virtual Error visit(EndBufferRecord &) = 0;
> >>>> +  virtual Error visit(FunctionRecord &) = 0;
> >>>> +};
> >>>> +
> >>>> +class RecordInitializer : public RecordVisitor {
> >>>> +  DataExtractor &E;
> >>>> +  uint32_t &OffsetPtr;
> >>>> +
> >>>> +public:
> >>>> +  explicit RecordInitializer(DataExtractor &DE, uint32_t &OP)
> >>>> +      : RecordVisitor(), E(DE), OffsetPtr(OP) {}
> >>>> +
> >>>> +  Error visit(BufferExtents &) override;
> >>>> +  Error visit(WallclockRecord &) override;
> >>>> +  Error visit(NewCPUIDRecord &) override;
> >>>> +  Error visit(TSCWrapRecord &) override;
> >>>> +  Error visit(CustomEventRecord &) override;
> >>>> +  Error visit(CallArgRecord &) override;
> >>>> +  Error visit(PIDRecord &) override;
> >>>> +  Error visit(NewBufferRecord &) override;
> >>>> +  Error visit(EndBufferRecord &) override;
> >>>> +  Error visit(FunctionRecord &) override;
> >>>> +};
> >>>> +
> >>>> +} // namespace xray
> >>>> +} // namespace llvm
> >>>> +
> >>>> +#endif // LLVM_LIB_XRAY_FDRRECORDS_H_
> >>>>
> >>>> Added: llvm/trunk/include/llvm/XRay/FDRTraceWriter.h
> >>>> URL: http://llvm.org/viewvc/llvm-
> >>>>
> project/llvm/trunk/include/llvm/XRay/FDRTraceWriter.h?rev=341029&view=a
> >>>> uto
> >>>>
> =======================================================================
> >>>> =======
> >>>> --- llvm/trunk/include/llvm/XRay/FDRTraceWriter.h (added)
> >>>> +++ llvm/trunk/include/llvm/XRay/FDRTraceWriter.h Thu Aug 30
> 00:22:21
> >>>> 2018
> >>>> @@ -0,0 +1,53 @@
> >>>> +//===- FDRTraceWriter.h - XRay FDR Trace Writer -----------------
> *-
> >>>> C++ -*-===//
> >>>> +//
> >>>> +//                     The LLVM Compiler Infrastructure
> >>>> +//
> >>>> +// This file is distributed under the University of Illinois Open
> >>>> Source
> >>>> +// License. See LICENSE.TXT for details.
> >>>> +//
> >>>> +//===------------------------------------------------------------
> -----
> >>>> -----===//
> >>>> +//
> >>>> +// Test a utility that can write out XRay FDR Mode formatted
> trace
> >>>> files.
> >>>> +//
> >>>> +//===------------------------------------------------------------
> -----
> >>>> -----===//
> >>>> +#ifndef LLVM_INCLUDE_LLVM_XRAY_FDRTRACEWRITER_H_
> >>>> +#define LLVM_INCLUDE_LLVM_XRAY_FDRTRACEWRITER_H_
> >>>> +
> >>>> +#include "llvm/Support/raw_ostream.h"
> >>>> +#include "llvm/XRay/FDRRecords.h"
> >>>> +#include "llvm/XRay/XRayRecord.h"
> >>>> +
> >>>> +namespace llvm {
> >>>> +namespace xray {
> >>>> +
> >>>> +/// The FDRTraceWriter allows us to hand-craft an XRay Flight
> Data
> >>>> Recorder
> >>>> +/// (FDR) mode log file. This is used primarily for testing,
> >>>> generating
> >>>> +/// sequences of FDR records that can be read/processed. It can
> also
> >>>> be used to
> >>>> +/// generate various kinds of execution traces without using the
> XRay
> >>>> runtime.
> >>>> +/// Note that this writer does not do any validation, but uses
> the
> >>>> types of
> >>>> +/// records defined in the FDRRecords.h file.
> >>>> +class FDRTraceWriter : public RecordVisitor {
> >>>> +public:
> >>>> +  // Construct an FDRTraceWriter associated with an output
> stream.
> >>>> +  explicit FDRTraceWriter(raw_ostream &O, const XRayFileHeader
> &H);
> >>>> +  ~FDRTraceWriter();
> >>>> +
> >>>> +  Error visit(BufferExtents &) override;
> >>>> +  Error visit(WallclockRecord &) override;
> >>>> +  Error visit(NewCPUIDRecord &) override;
> >>>> +  Error visit(TSCWrapRecord &) override;
> >>>> +  Error visit(CustomEventRecord &) override;
> >>>> +  Error visit(CallArgRecord &) override;
> >>>> +  Error visit(PIDRecord &) override;
> >>>> +  Error visit(NewBufferRecord &) override;
> >>>> +  Error visit(EndBufferRecord &) override;
> >>>> +  Error visit(FunctionRecord &) override;
> >>>> +
> >>>> +private:
> >>>> +  raw_ostream &OS;
> >>>> +};
> >>>> +
> >>>> +} // namespace xray
> >>>> +} // namespace llvm
> >>>> +
> >>>> +#endif // LLVM_INCLUDE_LLVM_XRAY_FDRTRACEWRITER_H_
> >>>>
> >>>> Modified: llvm/trunk/lib/XRay/CMakeLists.txt
> >>>> URL: http://llvm.org/viewvc/llvm-
> >>>>
> project/llvm/trunk/lib/XRay/CMakeLists.txt?rev=341029&r1=341028&r2=3410
> >>>> 29&view=diff
> >>>>
> =======================================================================
> >>>> =======
> >>>> --- llvm/trunk/lib/XRay/CMakeLists.txt (original)
> >>>> +++ llvm/trunk/lib/XRay/CMakeLists.txt Thu Aug 30 00:22:21 2018
> >>>> @@ -1,7 +1,10 @@
> >>>> add_llvm_library(LLVMXRay
> >>>> +  FDRRecords.cpp
> >>>> +  FDRTraceWriter.cpp
> >>>> FileHeaderReader.cpp
> >>>> InstrumentationMap.cpp
> >>>> -	Profile.cpp
> >>>> +  Profile.cpp
> >>>> +  RecordInitializer.cpp
> >>>> Trace.cpp
> >>>>
> >>>> ADDITIONAL_HEADER_DIRS
> >>>>
> >>>> Added: llvm/trunk/lib/XRay/FDRRecords.cpp
> >>>> URL: http://llvm.org/viewvc/llvm-
> >>>> project/llvm/trunk/lib/XRay/FDRRecords.cpp?rev=341029&view=auto
> >>>>
> =======================================================================
> >>>> =======
> >>>> --- llvm/trunk/lib/XRay/FDRRecords.cpp (added)
> >>>> +++ llvm/trunk/lib/XRay/FDRRecords.cpp Thu Aug 30 00:22:21 2018
> >>>> @@ -0,0 +1,31 @@
> >>>> +//===- FDRRecords.cpp -  XRay Flight Data Recorder Mode Records -
> -----
> >>>> -----===//
> >>>> +//
> >>>> +//                     The LLVM Compiler Infrastructure
> >>>> +//
> >>>> +// This file is distributed under the University of Illinois Open
> >>>> Source
> >>>> +// License. See LICENSE.TXT for details.
> >>>> +//
> >>>> +//===------------------------------------------------------------
> -----
> >>>> -----===//
> >>>> +//
> >>>> +// Define types and operations on these types that represent the
> >>>> different kinds
> >>>> +// of records we encounter in XRay flight data recorder mode
> traces.
> >>>> +//
> >>>> +//===------------------------------------------------------------
> -----
> >>>> -----===//
> >>>> +#include "llvm/XRay/FDRRecords.h"
> >>>> +
> >>>> +namespace llvm {
> >>>> +namespace xray {
> >>>> +
> >>>> +Error BufferExtents::apply(RecordVisitor &V) { return
> V.visit(*this);
> >>>> }
> >>>> +Error WallclockRecord::apply(RecordVisitor &V) { return
> >>>> V.visit(*this); }
> >>>> +Error NewCPUIDRecord::apply(RecordVisitor &V) { return
> V.visit(*this);
> >>>> }
> >>>> +Error TSCWrapRecord::apply(RecordVisitor &V) { return
> V.visit(*this);
> >>>> }
> >>>> +Error CustomEventRecord::apply(RecordVisitor &V) { return
> >>>> V.visit(*this); }
> >>>> +Error CallArgRecord::apply(RecordVisitor &V) { return
> V.visit(*this);
> >>>> }
> >>>> +Error PIDRecord::apply(RecordVisitor &V) { return V.visit(*this);
> }
> >>>> +Error NewBufferRecord::apply(RecordVisitor &V) { return
> >>>> V.visit(*this); }
> >>>> +Error EndBufferRecord::apply(RecordVisitor &V) { return
> >>>> V.visit(*this); }
> >>>> +Error FunctionRecord::apply(RecordVisitor &V) { return
> V.visit(*this);
> >>>> }
> >>>> +
> >>>> +} // namespace xray
> >>>> +} // namespace llvm
> >>>>
> >>>> Added: llvm/trunk/lib/XRay/FDRTraceWriter.cpp
> >>>> URL: http://llvm.org/viewvc/llvm-
> >>>>
> project/llvm/trunk/lib/XRay/FDRTraceWriter.cpp?rev=341029&view=auto
> >>>>
> =======================================================================
> >>>> =======
> >>>> --- llvm/trunk/lib/XRay/FDRTraceWriter.cpp (added)
> >>>> +++ llvm/trunk/lib/XRay/FDRTraceWriter.cpp Thu Aug 30 00:22:21
> 2018
> >>>> @@ -0,0 +1,145 @@
> >>>> +//===- FDRTraceWriter.cpp - XRay FDR Trace Writer ---------------
> *-
> >>>> C++ -*-===//
> >>>> +//
> >>>> +//                     The LLVM Compiler Infrastructure
> >>>> +//
> >>>> +// This file is distributed under the University of Illinois Open
> >>>> Source
> >>>> +// License. See LICENSE.TXT for details.
> >>>> +//
> >>>> +//===------------------------------------------------------------
> -----
> >>>> -----===//
> >>>> +//
> >>>> +// Test a utility that can write out XRay FDR Mode formatted
> trace
> >>>> files.
> >>>> +//
> >>>> +//===------------------------------------------------------------
> -----
> >>>> -----===//
> >>>> +#include "llvm/XRay/FDRTraceWriter.h"
> >>>> +#include <tuple>
> >>>> +
> >>>> +namespace llvm {
> >>>> +namespace xray {
> >>>> +
> >>>> +namespace {
> >>>> +
> >>>> +struct alignas(32) FileHeader {
> >>>> +  uint16_t Version;
> >>>> +  uint16_t Type;
> >>>> +  bool ConstantTSC : 1;
> >>>> +  bool NonstopTSC : 1;
> >>>> +  alignas(8) uint64_t CycleFrequency;
> >>>> +  char FreeForm[16];
> >>>> +};
> >>>> +
> >>>> +struct MetadataBlob {
> >>>> +  uint8_t Type : 1;
> >>>> +  uint8_t RecordKind : 7;
> >>>> +  char Data[15];
> >>>> +} __attribute__((packed));
> >>>> +
> >>>> +struct FunctionDeltaBlob {
> >>>> +  uint8_t Type : 1;
> >>>> +  uint8_t RecordKind : 3;
> >>>> +  int FuncId : 28;
> >>>> +  uint32_t TSCDelta;
> >>>> +} __attribute__((packed));
> >>>> +
> >>>> +template <size_t Index> struct IndexedMemcpy {
> >>>> +  template <
> >>>> +      class Tuple,
> >>>> +      typename std::enable_if<
> >>>> +          (Index <
> >>>> +           std::tuple_size<typename
> >>>> std::remove_reference<Tuple>::type>::value),
> >>>> +          int>::type = 0>
> >>>> +  static void Copy(char *Dest, Tuple &&T) {
> >>>> +    auto Next = static_cast<char *>(std::memcpy(
> >>>> +                    Dest, reinterpret_cast<const char
> >>>> *>(&std::get<Index>(T)),
> >>>> +                    sizeof(std::get<Index>(T)))) +
> >>>> +                sizeof(std::get<Index>(T));
> >>>> +    IndexedMemcpy<Index + 1>::Copy(Next, T);
> >>>> +  }
> >>>> +
> >>>> +  template <
> >>>> +      class Tuple,
> >>>> +      typename std::enable_if<
> >>>> +          (Index >=
> >>>> +           std::tuple_size<typename
> >>>> std::remove_reference<Tuple>::type>::value),
> >>>> +          int>::type = 0>
> >>>> +  static void Copy(char *, Tuple &&) {}
> >>>> +};
> >>>> +
> >>>> +template <uint8_t Kind, class... Data>
> >>>> +Error writeMetadata(raw_ostream &OS, Data... Ds) {
> >>>> +  MetadataBlob B;
> >>>> +  B.Type = 1;
> >>>> +  B.RecordKind = Kind;
> >>>> +  IndexedMemcpy<0>::Copy(B.Data, std::make_tuple(Ds...));
> >>>> +  OS.write(reinterpret_cast<const char *>(&B),
> sizeof(MetadataBlob));
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +} // namespace
> >>>> +
> >>>> +FDRTraceWriter::FDRTraceWriter(raw_ostream &O, const
> XRayFileHeader
> >>>> &H)
> >>>> +    : OS(O) {
> >>>> +  // We need to re-construct a header, by writing the fields we
> care
> >>>> about for
> >>>> +  // traces, in the format that the runtime would have written.
> >>>> +  FileHeader Raw;
> >>>> +  Raw.Version = H.Version;
> >>>> +  Raw.Type = H.Type;
> >>>> +  Raw.ConstantTSC = H.ConstantTSC;
> >>>> +  Raw.NonstopTSC = H.NonstopTSC;
> >>>> +  Raw.CycleFrequency = H.CycleFrequency;
> >>>> +  memcpy(&Raw.FreeForm, H.FreeFormData, 16);
> >>>> +  OS.write(reinterpret_cast<const char *>(&Raw),
> >>>> sizeof(XRayFileHeader));
> >>>> +}
> >>>> +
> >>>> +FDRTraceWriter::~FDRTraceWriter() {}
> >>>> +
> >>>> +Error FDRTraceWriter::visit(BufferExtents &R) {
> >>>> +  return writeMetadata<7u>(OS, R.size());
> >>>> +}
> >>>> +
> >>>> +Error FDRTraceWriter::visit(WallclockRecord &R) {
> >>>> +  return writeMetadata<4u>(OS, R.seconds(), R.nanos());
> >>>> +}
> >>>> +
> >>>> +Error FDRTraceWriter::visit(NewCPUIDRecord &R) {
> >>>> +  return writeMetadata<2u>(OS, R.cpuid());
> >>>> +}
> >>>> +
> >>>> +Error FDRTraceWriter::visit(TSCWrapRecord &R) {
> >>>> +  return writeMetadata<3u>(OS, R.tsc());
> >>>> +}
> >>>> +
> >>>> +Error FDRTraceWriter::visit(CustomEventRecord &R) {
> >>>> +  if (auto E = writeMetadata<5u>(OS, R.size(), R.tsc()))
> >>>> +    return E;
> >>>> +  OS.write(R.data().data(), R.data().size());
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +Error FDRTraceWriter::visit(CallArgRecord &R) {
> >>>> +  return writeMetadata<6u>(OS, R.arg());
> >>>> +}
> >>>> +
> >>>> +Error FDRTraceWriter::visit(PIDRecord &R) {
> >>>> +  return writeMetadata<9u>(OS, R.pid());
> >>>> +}
> >>>> +
> >>>> +Error FDRTraceWriter::visit(NewBufferRecord &R) {
> >>>> +  return writeMetadata<0u>(OS, R.tid());
> >>>> +}
> >>>> +
> >>>> +Error FDRTraceWriter::visit(EndBufferRecord &R) {
> >>>> +  return writeMetadata<1u>(OS, 0);
> >>>> +}
> >>>> +
> >>>> +Error FDRTraceWriter::visit(FunctionRecord &R) {
> >>>> +  FunctionDeltaBlob B;
> >>>> +  B.Type = 0;
> >>>> +  B.RecordKind = static_cast<uint8_t>(R.recordType());
> >>>> +  B.FuncId = R.functionId();
> >>>> +  B.TSCDelta = R.delta();
> >>>> +  OS.write(reinterpret_cast<const char *>(&B),
> >>>> sizeof(FunctionDeltaBlob));
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +} // namespace xray
> >>>> +} // namespace llvm
> >>>>
> >>>> Added: llvm/trunk/lib/XRay/RecordInitializer.cpp
> >>>> URL: http://llvm.org/viewvc/llvm-
> >>>>
> project/llvm/trunk/lib/XRay/RecordInitializer.cpp?rev=341029&view=auto
> >>>>
> =======================================================================
> >>>> =======
> >>>> --- llvm/trunk/lib/XRay/RecordInitializer.cpp (added)
> >>>> +++ llvm/trunk/lib/XRay/RecordInitializer.cpp Thu Aug 30 00:22:21
> 2018
> >>>> @@ -0,0 +1,247 @@
> >>>> +//===- FDRRecordProducer.cpp - XRay FDR Mode Record Producer ----
> -----
> >>>> -----===//
> >>>> +//
> >>>> +//                     The LLVM Compiler Infrastructure
> >>>> +//
> >>>> +// This file is distributed under the University of Illinois Open
> >>>> Source
> >>>> +// License. See LICENSE.TXT for details.
> >>>> +//
> >>>> +//===------------------------------------------------------------
> -----
> >>>> -----===//
> >>>> +#include "llvm/XRay/FDRRecords.h"
> >>>> +
> >>>> +namespace llvm {
> >>>> +namespace xray {
> >>>> +
> >>>> +Error RecordInitializer::visit(BufferExtents &R) {
> >>>> +  if (!E.isValidOffsetForDataOfSize(OffsetPtr, sizeof(uint64_t)))
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_address),
> >>>> +                             "Invalid offset for a buffer extent
> >>>> (%d).",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  auto PreReadOffset = OffsetPtr;
> >>>> +  R.Size = E.getU64(&OffsetPtr);
> >>>> +  if (PreReadOffset == OffsetPtr)
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_message),
> >>>> +                             "Cannot read buffer extent at offset
> >>>> %d.",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr -
> >>>> PreReadOffset);
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +Error RecordInitializer::visit(WallclockRecord &R) {
> >>>> +  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
> >>>> +
> >>>> MetadataRecord::kMetadataBodySize))
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_address),
> >>>> +                             "Invalid offset for a wallclock
> record
> >>>> (%d).",
> >>>> +                             OffsetPtr);
> >>>> +  auto BeginOffset = OffsetPtr;
> >>>> +  auto PreReadOffset = OffsetPtr;
> >>>> +  R.Seconds = E.getU64(&OffsetPtr);
> >>>> +  if (OffsetPtr == PreReadOffset)
> >>>> +    return createStringError(
> >>>> +        std::make_error_code(std::errc::bad_message),
> >>>> +        "Cannot read wall clock 'seconds' field at offset %d.",
> >>>> OffsetPtr);
> >>>> +
> >>>> +  PreReadOffset = OffsetPtr;
> >>>> +  R.Nanos = E.getU32(&OffsetPtr);
> >>>> +  if (OffsetPtr == PreReadOffset)
> >>>> +    return createStringError(
> >>>> +        std::make_error_code(std::errc::bad_message),
> >>>> +        "Cannot read wall clock 'nanos' field at offset %d.",
> >>>> OffsetPtr);
> >>>> +
> >>>> +  // Align to metadata record size boundary.
> >>>> +  assert(OffsetPtr - BeginOffset <=
> >>>> MetadataRecord::kMetadataBodySize);
> >>>> +  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr -
> >>>> BeginOffset);
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +Error RecordInitializer::visit(NewCPUIDRecord &R) {
> >>>> +  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
> >>>> +
> >>>> MetadataRecord::kMetadataBodySize))
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_address),
> >>>> +                             "Invalid offset for a new cpu id
> record
> >>>> (%d).",
> >>>> +                             OffsetPtr);
> >>>> +  auto PreReadOffset = OffsetPtr;
> >>>> +  R.CPUId = E.getU16(&OffsetPtr);
> >>>> +  if (OffsetPtr == PreReadOffset)
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_message),
> >>>> +                             "Cannot read CPU id at offset %d.",
> >>>> OffsetPtr);
> >>>> +
> >>>> +  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr -
> >>>> PreReadOffset);
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +Error RecordInitializer::visit(TSCWrapRecord &R) {
> >>>> +  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
> >>>> +
> >>>> MetadataRecord::kMetadataBodySize))
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_address),
> >>>> +                             "Invalid offset for a new TSC wrap
> record
> >>>> (%d).",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  auto PreReadOffset = OffsetPtr;
> >>>> +  R.BaseTSC = E.getU64(&OffsetPtr);
> >>>> +  if (PreReadOffset == OffsetPtr)
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_message),
> >>>> +                             "Cannot read TSC wrap record at
> offset
> >>>> %d.",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr -
> >>>> PreReadOffset);
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +Error RecordInitializer::visit(CustomEventRecord &R) {
> >>>> +  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
> >>>> +
> >>>> MetadataRecord::kMetadataBodySize))
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_address),
> >>>> +                             "Invalid offset for a custom event
> record
> >>>> (%d).",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  auto BeginOffset = OffsetPtr;
> >>>> +  auto PreReadOffset = OffsetPtr;
> >>>> +  R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
> >>>> +  if (PreReadOffset == OffsetPtr)
> >>>> +    return createStringError(
> >>>> +        std::make_error_code(std::errc::bad_message),
> >>>> +        "Cannot read a custom event record size field offset
> %d.",
> >>>> OffsetPtr);
> >>>> +
> >>>> +  PreReadOffset = OffsetPtr;
> >>>> +  R.TSC = E.getU64(&OffsetPtr);
> >>>> +  if (PreReadOffset == OffsetPtr)
> >>>> +    return createStringError(
> >>>> +        std::make_error_code(std::errc::bad_message),
> >>>> +        "Cannot read a custom event TSC field at offset %d.",
> >>>> OffsetPtr);
> >>>> +
> >>>> +  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr -
> >>>> BeginOffset);
> >>>> +
> >>>> +  // Next we read in a fixed chunk of data from the given offset.
> >>>> +  if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
> >>>> +    return createStringError(
> >>>> +        std::make_error_code(std::errc::bad_address),
> >>>> +        "Cannot read %d bytes of custom event data from offset
> %d.",
> >>>> R.Size,
> >>>> +        OffsetPtr);
> >>>> +
> >>>> +  std::vector<uint8_t> Buffer;
> >>>> +  Buffer.resize(R.Size);
> >>>> +  if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) !=
> Buffer.data())
> >>>> +    return createStringError(
> >>>> +        std::make_error_code(std::errc::bad_message),
> >>>> +        "Failed reading data into buffer of size %d at offset
> %d.",
> >>>> R.Size,
> >>>> +        OffsetPtr);
> >>>> +  R.Data.assign(Buffer.begin(), Buffer.end());
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +Error RecordInitializer::visit(CallArgRecord &R) {
> >>>> +  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
> >>>> +
> >>>> MetadataRecord::kMetadataBodySize))
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_address),
> >>>> +                             "Invalid offset for a call argument
> >>>> record (%d).",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  auto PreReadOffset = OffsetPtr;
> >>>> +  R.Arg = E.getU64(&OffsetPtr);
> >>>> +  if (PreReadOffset == OffsetPtr)
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_message),
> >>>> +                             "Cannot read a call arg record at
> offset
> >>>> %d.",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr -
> >>>> PreReadOffset);
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +Error RecordInitializer::visit(PIDRecord &R) {
> >>>> +  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
> >>>> +
> >>>> MetadataRecord::kMetadataBodySize))
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_address),
> >>>> +                             "Invalid offset for a process ID
> record
> >>>> (%d).",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  auto PreReadOffset = OffsetPtr;
> >>>> +  R.PID = E.getU64(&OffsetPtr);
> >>>> +  if (PreReadOffset == OffsetPtr)
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_message),
> >>>> +                             "Cannot read a process ID record at
> >>>> offset %d.",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr -
> >>>> PreReadOffset);
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +Error RecordInitializer::visit(NewBufferRecord &R) {
> >>>> +  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
> >>>> +
> >>>> MetadataRecord::kMetadataBodySize))
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_address),
> >>>> +                             "Invalid offset for a new buffer
> record
> >>>> (%d).",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  auto PreReadOffset = OffsetPtr;
> >>>> +  R.TID = E.getSigned(&OffsetPtr, sizeof(int32_t));
> >>>> +  if (PreReadOffset == OffsetPtr)
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_message),
> >>>> +                             "Cannot read a new buffer record at
> >>>> offset %d.",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr -
> >>>> PreReadOffset);
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +Error RecordInitializer::visit(EndBufferRecord &R) {
> >>>> +  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
> >>>> +
> >>>> MetadataRecord::kMetadataBodySize))
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_address),
> >>>> +                             "Invalid offset for an end-of-buffer
> >>>> record (%d).",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  OffsetPtr += MetadataRecord::kMetadataBodySize;
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +Error RecordInitializer::visit(FunctionRecord &R) {
> >>>> +  // For function records, we need to retreat one byte back to
> read a
> >>>> full
> >>>> +  // unsigned 32-bit value. The first four bytes will have the
> >>>> following
> >>>> +  // layout:
> >>>> +  //
> >>>> +  //   bit  0     : function record indicator (must be 0)
> >>>> +  //   bits 1..3  : function record type
> >>>> +  //   bits 4..32 : function id
> >>>> +  //
> >>>> +  if (OffsetPtr == 0 || !E.isValidOffsetForDataOfSize(
> >>>> +                            --OffsetPtr,
> >>>> FunctionRecord::kFunctionRecordSize))
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_address),
> >>>> +                             "Invalid offset for a function
> record
> >>>> (%d).",
> >>>> +                             OffsetPtr);
> >>>> +
> >>>> +  auto BeginOffset = OffsetPtr;
> >>>> +  auto PreReadOffset = BeginOffset;
> >>>> +  uint32_t Buffer = E.getU32(&OffsetPtr);
> >>>> +  if (PreReadOffset == OffsetPtr)
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_address),
> >>>> +                             "Cannot read function id field from
> >>>> offset %d.",
> >>>> +                             OffsetPtr);
> >>>> +  unsigned FunctionType = (Buffer >> 1) & 0x07;
> >>>> +  switch (FunctionType) {
> >>>> +  case static_cast<unsigned>(RecordTypes::ENTER):
> >>>> +  case static_cast<unsigned>(RecordTypes::ENTER_ARG):
> >>>> +  case static_cast<unsigned>(RecordTypes::EXIT):
> >>>> +  case static_cast<unsigned>(RecordTypes::TAIL_EXIT):
> >>>> +    R.Kind = static_cast<RecordTypes>(FunctionType);
> >>>> +    break;
> >>>> +  default:
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_message),
> >>>> +                             "Unknown function record type '%d'
> at
> >>>> offset %d.",
> >>>> +                             FunctionType, BeginOffset);
> >>>> +  }
> >>>> +
> >>>> +  R.FuncId = Buffer >> 4;
> >>>> +  PreReadOffset = OffsetPtr;
> >>>> +  R.Delta = E.getU32(&OffsetPtr);
> >>>> +  if (OffsetPtr == PreReadOffset)
> >>>> +    return
> >>>> createStringError(std::make_error_code(std::errc::bad_message),
> >>>> +                             "Failed reading TSC delta from
> offset
> >>>> %d.",
> >>>> +                             OffsetPtr);
> >>>> +  assert(FunctionRecord::kFunctionRecordSize == (OffsetPtr -
> >>>> BeginOffset));
> >>>> +  return Error::success();
> >>>> +}
> >>>> +
> >>>> +} // namespace xray
> >>>> +} // namespace llvm
> >>>>
> >>>> Modified: llvm/trunk/unittests/XRay/CMakeLists.txt
> >>>> URL: http://llvm.org/viewvc/llvm-
> >>>>
> project/llvm/trunk/unittests/XRay/CMakeLists.txt?rev=341029&r1=341028&r
> >>>> 2=341029&view=diff
> >>>>
> =======================================================================
> >>>> =======
> >>>> --- llvm/trunk/unittests/XRay/CMakeLists.txt (original)
> >>>> +++ llvm/trunk/unittests/XRay/CMakeLists.txt Thu Aug 30 00:22:21
> 2018
> >>>> @@ -1,9 +1,10 @@
> >>>> set(LLVM_LINK_COMPONENTS
> >>>> Support
> >>>> -	XRay
> >>>> +  XRay
> >>>> )
> >>>>
> >>>> add_llvm_unittest(XRayTests
> >>>> +  FDRTraceWriterTest.cpp
> >>>> GraphTest.cpp
> >>>> 	ProfileTest.cpp
> >>>> )
> >>>>
> >>>> Added: llvm/trunk/unittests/XRay/FDRTraceWriterTest.cpp
> >>>> URL: http://llvm.org/viewvc/llvm-
> >>>>
> project/llvm/trunk/unittests/XRay/FDRTraceWriterTest.cpp?rev=341029&vie
> >>>> w=auto
> >>>>
> =======================================================================
> >>>> =======
> >>>> --- llvm/trunk/unittests/XRay/FDRTraceWriterTest.cpp (added)
> >>>> +++ llvm/trunk/unittests/XRay/FDRTraceWriterTest.cpp Thu Aug 30
> >>>> 00:22:21 2018
> >>>> @@ -0,0 +1,175 @@
> >>>> +//===- llvm/unittest/XRay/FDRTraceWriterTest.cpp ----------------
> *-
> >>>> C++ -*-===//
> >>>> +//
> >>>> +//                     The LLVM Compiler Infrastructure
> >>>> +//
> >>>> +// This file is distributed under the University of Illinois Open
> >>>> Source
> >>>> +// License. See LICENSE.TXT for details.
> >>>> +//
> >>>> +//===------------------------------------------------------------
> -----
> >>>> -----===//
> >>>> +//
> >>>> +// Test a utility that can write out XRay FDR Mode formatted
> trace
> >>>> files.
> >>>> +//
> >>>> +//===------------------------------------------------------------
> -----
> >>>> -----===//
> >>>> +#include "llvm/XRay/FDRTraceWriter.h"
> >>>> +#include "llvm/Support/raw_ostream.h"
> >>>> +#include "llvm/XRay/FDRLogBuilder.h"
> >>>> +#include "llvm/XRay/FDRRecords.h"
> >>>> +#include "llvm/XRay/Trace.h"
> >>>> +#include "gmock/gmock.h"
> >>>> +#include "gtest/gtest.h"
> >>>> +#include <string>
> >>>> +
> >>>> +namespace llvm {
> >>>> +namespace xray {
> >>>> +namespace {
> >>>> +
> >>>> +using testing::ElementsAre;
> >>>> +using testing::Eq;
> >>>> +using testing::Field;
> >>>> +using testing::IsEmpty;
> >>>> +using testing::Not;
> >>>> +
> >>>> +// We want to be able to create an instance of an FDRTraceWriter
> and
> >>>> associate
> >>>> +// it with a stream, which could be loaded and turned into a
> Trace
> >>>> instance.
> >>>> +// This test writes out version 3 trace logs.
> >>>> +TEST(FDRTraceWriterTest, WriteToStringBufferVersion3) {
> >>>> +  std::string Data;
> >>>> +  raw_string_ostream OS(Data);
> >>>> +  XRayFileHeader H;
> >>>> +  H.Version = 3;
> >>>> +  H.Type = 1;
> >>>> +  H.ConstantTSC = true;
> >>>> +  H.NonstopTSC = true;
> >>>> +  H.CycleFrequency = 3e9;
> >>>> +  FDRTraceWriter Writer(OS, H);
> >>>> +  auto L = LogBuilder()
> >>>> +               .add<BufferExtents>(80)
> >>>> +               .add<NewBufferRecord>(1)
> >>>> +               .add<WallclockRecord>(1, 1)
> >>>> +               .add<PIDRecord>(1)
> >>>> +               .add<NewCPUIDRecord>(1)
> >>>> +               .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
> >>>> +               .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
> >>>> +               .consume();
> >>>> +  for (auto &P : L)
> >>>> +    ASSERT_FALSE(errorToBool(P->apply(Writer)));
> >>>> +  OS.flush();
> >>>> +
> >>>> +  // Then from here we load the Trace file.
> >>>> +  DataExtractor DE(Data, true, 8);
> >>>> +  auto TraceOrErr = loadTrace(DE, true);
> >>>> +  if (!TraceOrErr)
> >>>> +    FAIL() << TraceOrErr.takeError();
> >>>> +  auto &Trace = TraceOrErr.get();
> >>>> +
> >>>> +  ASSERT_THAT(Trace, Not(IsEmpty()));
> >>>> +  ASSERT_THAT(
> >>>> +      Trace,
> >>>> +      ElementsAre(AllOf(Field(&XRayRecord::FuncId, Eq(1)),
> >>>> +                        Field(&XRayRecord::TId, Eq(1u)),
> >>>> +                        Field(&XRayRecord::CPU, Eq(1u)),
> >>>> +                        Field(&XRayRecord::Type,
> >>>> Eq(RecordTypes::ENTER))),
> >>>> +                  AllOf(Field(&XRayRecord::FuncId, Eq(1)),
> >>>> +                        Field(&XRayRecord::TId, Eq(1u)),
> >>>> +                        Field(&XRayRecord::CPU, Eq(1u)),
> >>>> +                        Field(&XRayRecord::Type,
> >>>> Eq(RecordTypes::EXIT)))));
> >>>> +}
> >>>> +
> >>>> +// This version is almost exactly the same as above, except
> writing
> >>>> version 2
> >>>> +// logs, without the PID records.
> >>>> +TEST(FDRTraceWriterTest, WriteToStringBufferVersion2) {
> >>>> +  std::string Data;
> >>>> +  raw_string_ostream OS(Data);
> >>>> +  XRayFileHeader H;
> >>>> +  H.Version = 2;
> >>>> +  H.Type = 1;
> >>>> +  H.ConstantTSC = true;
> >>>> +  H.NonstopTSC = true;
> >>>> +  H.CycleFrequency = 3e9;
> >>>> +  FDRTraceWriter Writer(OS, H);
> >>>> +  auto L = LogBuilder()
> >>>> +               .add<BufferExtents>(64)
> >>>> +               .add<NewBufferRecord>(1)
> >>>> +               .add<WallclockRecord>(1, 1)
> >>>> +               .add<NewCPUIDRecord>(1)
> >>>> +               .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
> >>>> +               .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
> >>>> +               .consume();
> >>>> +  for (auto &P : L)
> >>>> +    ASSERT_FALSE(errorToBool(P->apply(Writer)));
> >>>> +  OS.flush();
> >>>> +
> >>>> +  // Then from here we load the Trace file.
> >>>> +  DataExtractor DE(Data, true, 8);
> >>>> +  auto TraceOrErr = loadTrace(DE, true);
> >>>> +  if (!TraceOrErr)
> >>>> +    FAIL() << TraceOrErr.takeError();
> >>>> +  auto &Trace = TraceOrErr.get();
> >>>> +
> >>>> +  ASSERT_THAT(Trace, Not(IsEmpty()));
> >>>> +  ASSERT_THAT(
> >>>> +      Trace,
> >>>> +      ElementsAre(AllOf(Field(&XRayRecord::FuncId, Eq(1)),
> >>>> +                        Field(&XRayRecord::TId, Eq(1u)),
> >>>> +                        Field(&XRayRecord::CPU, Eq(1u)),
> >>>> +                        Field(&XRayRecord::Type,
> >>>> Eq(RecordTypes::ENTER))),
> >>>> +                  AllOf(Field(&XRayRecord::FuncId, Eq(1)),
> >>>> +                        Field(&XRayRecord::TId, Eq(1u)),
> >>>> +                        Field(&XRayRecord::CPU, Eq(1u)),
> >>>> +                        Field(&XRayRecord::Type,
> >>>> Eq(RecordTypes::EXIT)))));
> >>>> +}
> >>>> +
> >>>> +// This covers version 1 of the log, without a BufferExtents
> record
> >>>> but has an
> >>>> +// explicit EndOfBuffer record.
> >>>> +TEST(FDRTraceWriterTest, WriteToStringBufferVersion1) {
> >>>> +  std::string Data;
> >>>> +  raw_string_ostream OS(Data);
> >>>> +  XRayFileHeader H;
> >>>> +  H.Version = 1;
> >>>> +  H.Type = 1;
> >>>> +  H.ConstantTSC = true;
> >>>> +  H.NonstopTSC = true;
> >>>> +  H.CycleFrequency = 3e9;
> >>>> +  // Write the size of buffers out, arbitrarily it's 4k.
> >>>> +  constexpr uint64_t BufferSize = 4096;
> >>>> +  std::memcpy(H.FreeFormData, reinterpret_cast<const char
> >>>> *>(&BufferSize),
> >>>> +              sizeof(BufferSize));
> >>>> +  FDRTraceWriter Writer(OS, H);
> >>>> +  auto L = LogBuilder()
> >>>> +               .add<NewBufferRecord>(1)
> >>>> +               .add<WallclockRecord>(1, 1)
> >>>> +               .add<NewCPUIDRecord>(1)
> >>>> +               .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
> >>>> +               .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
> >>>> +               .add<EndBufferRecord>()
> >>>> +               .consume();
> >>>> +  for (auto &P : L)
> >>>> +    ASSERT_FALSE(errorToBool(P->apply(Writer)));
> >>>> +
> >>>> +  // We need to pad the buffer with 4016 (4096 - 80) bytes of
> zeros.
> >>>> +  OS.write_zeros(4016);
> >>>> +  OS.flush();
> >>>> +
> >>>> +  // Then from here we load the Trace file.
> >>>> +  DataExtractor DE(Data, true, 8);
> >>>> +  auto TraceOrErr = loadTrace(DE, true);
> >>>> +  if (!TraceOrErr)
> >>>> +    FAIL() << TraceOrErr.takeError();
> >>>> +  auto &Trace = TraceOrErr.get();
> >>>> +
> >>>> +  ASSERT_THAT(Trace, Not(IsEmpty()));
> >>>> +  ASSERT_THAT(
> >>>> +      Trace,
> >>>> +      ElementsAre(AllOf(Field(&XRayRecord::FuncId, Eq(1)),
> >>>> +                        Field(&XRayRecord::TId, Eq(1u)),
> >>>> +                        Field(&XRayRecord::CPU, Eq(1u)),
> >>>> +                        Field(&XRayRecord::Type,
> >>>> Eq(RecordTypes::ENTER))),
> >>>> +                  AllOf(Field(&XRayRecord::FuncId, Eq(1)),
> >>>> +                        Field(&XRayRecord::TId, Eq(1u)),
> >>>> +                        Field(&XRayRecord::CPU, Eq(1u)),
> >>>> +                        Field(&XRayRecord::Type,
> >>>> Eq(RecordTypes::EXIT)))));
> >>>> +}
> >>>> +
> >>>> +} // namespace
> >>>> +} // namespace xray
> >>>> +} // namespace llvm
> >>>>
> >>>>
> >>>> _______________________________________________
> >>>> llvm-commits mailing list
> >>>> llvm-commits at lists.llvm.org
> >>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> >>> _______________________________________________
> >>> llvm-commits mailing list
> >>> llvm-commits at lists.llvm.org
> >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> >>
> >> -- Dean
> >>
> >
> > -- Dean
> >
> 
> -- Dean



More information about the llvm-commits mailing list