[llvm] r341628 - [XRay] Add a BlockVerifier visitor for FDR Records
Dean Michael Berris via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 6 20:44:19 PDT 2018
Yes, sorry Craig, my bad -- reverted in r341631.
On Fri, Sep 7, 2018 at 12:59 PM Craig Topper <craig.topper at gmail.com> wrote:
>
> This is failing my build because the tuple constructor isn't constexpr in C++11. It's only C++14 and newer.
>
> lib/XRay/BlockVerifier.cpp:58:7: error: constexpr variable 'TransitionTable' must be initialized by a constant expression
>
> TransitionTable{{{State::Unknown,
>
> ^ ~~~~~~~~~~~~~~~~~~
>
> lib/XRay/BlockVerifier.cpp:58:24: note: non-constexpr constructor 'tuple<true, false>' cannot be used in a constant expression
>
> TransitionTable{{{State::Unknown,
>
>
> ~Craig
>
>
> On Thu, Sep 6, 2018 at 7:26 PM Dean Michael Berris via llvm-commits <llvm-commits at lists.llvm.org> wrote:
>>
>> Author: dberris
>> Date: Thu Sep 6 19:25:06 2018
>> New Revision: 341628
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=341628&view=rev
>> Log:
>> [XRay] Add a BlockVerifier visitor for FDR Records
>>
>> Summary:
>> This patch implements a `BlockVerifier` type which enforces the
>> invariants of the log structure of FDR mode logs on a per-block basis.
>> This ensures that the data we encounter from an FDR mode log
>> semantically correct (i.e. that records follow the documented "grammar"
>> for FDR mode log records).
>>
>> This is another part of the refactoring of D50441.
>>
>> Reviewers: mboerger, eizan
>>
>> Subscribers: mgorny, hiraditya, llvm-commits
>>
>> Differential Revision: https://reviews.llvm.org/D51723
>>
>> Added:
>> llvm/trunk/include/llvm/XRay/BlockVerifier.h
>> llvm/trunk/lib/XRay/BlockVerifier.cpp
>> llvm/trunk/unittests/XRay/FDRBlockVerifierTest.cpp
>> Modified:
>> llvm/trunk/lib/XRay/CMakeLists.txt
>> llvm/trunk/unittests/XRay/CMakeLists.txt
>>
>> Added: llvm/trunk/include/llvm/XRay/BlockVerifier.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/XRay/BlockVerifier.h?rev=341628&view=auto
>> ==============================================================================
>> --- llvm/trunk/include/llvm/XRay/BlockVerifier.h (added)
>> +++ llvm/trunk/include/llvm/XRay/BlockVerifier.h Thu Sep 6 19:25:06 2018
>> @@ -0,0 +1,69 @@
>> +//===- BlockVerifier.h - FDR Block Verifier -------------------------------===//
>> +//
>> +// The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// An implementation of the RecordVisitor which verifies a sequence of records
>> +// associated with a block, following the FDR mode log format's specifications.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +#ifndef LLVM_INCLUDE_LLVM_XRAY_BLOCKVERIFIER_H_
>> +#define LLVM_INCLUDE_LLVM_XRAY_BLOCKVERIFIER_H_
>> +
>> +#include "llvm/XRay/FDRRecords.h"
>> +#include <array>
>> +#include <bitset>
>> +
>> +namespace llvm {
>> +namespace xray {
>> +
>> +class BlockVerifier : public RecordVisitor {
>> +public:
>> + // We force State elements to be size_t, to be used as indices for containers.
>> + enum class State : std::size_t {
>> + Unknown,
>> + BufferExtents,
>> + NewBuffer,
>> + WallClockTime,
>> + PIDEntry,
>> + NewCPUId,
>> + TSCWrap,
>> + CustomEvent,
>> + Function,
>> + CallArg,
>> + EndOfBuffer,
>> + StateMax,
>> + };
>> +
>> +private:
>> + // We keep track of the current record seen by the verifier.
>> + State CurrentRecord = State::Unknown;
>> +
>> + // Transitions the current record to the new record, records an error on
>> + // invalid transitions.
>> + Error transition(State To);
>> +
>> +public:
>> + 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;
>> +
>> + Error verify();
>> + void reset();
>> +};
>> +
>> +} // namespace xray
>> +} // namespace llvm
>> +
>> +#endif // LLVM_INCLUDE_LLVM_XRAY_BLOCKVERIFIER_H_
>>
>> Added: llvm/trunk/lib/XRay/BlockVerifier.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/XRay/BlockVerifier.cpp?rev=341628&view=auto
>> ==============================================================================
>> --- llvm/trunk/lib/XRay/BlockVerifier.cpp (added)
>> +++ llvm/trunk/lib/XRay/BlockVerifier.cpp Thu Sep 6 19:25:06 2018
>> @@ -0,0 +1,182 @@
>> +//===- BlockVerifier.cpp - FDR Block Verifier -----------------------------===//
>> +//
>> +// The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +#include "llvm/XRay/BlockVerifier.h"
>> +#include "llvm/Support/Error.h"
>> +
>> +namespace llvm {
>> +namespace xray {
>> +namespace {
>> +
>> +constexpr unsigned long long mask(BlockVerifier::State S) {
>> + return 1uLL << static_cast<std::size_t>(S);
>> +}
>> +
>> +constexpr std::size_t number(BlockVerifier::State S) {
>> + return static_cast<std::size_t>(S);
>> +}
>> +
>> +StringRef recordToString(BlockVerifier::State R) {
>> + switch (R) {
>> + case BlockVerifier::State::BufferExtents:
>> + return "BufferExtents";
>> + case BlockVerifier::State::NewBuffer:
>> + return "NewBuffer";
>> + case BlockVerifier::State::WallClockTime:
>> + return "WallClockTime";
>> + case BlockVerifier::State::PIDEntry:
>> + return "PIDEntry";
>> + case BlockVerifier::State::NewCPUId:
>> + return "NewCPUId";
>> + case BlockVerifier::State::TSCWrap:
>> + return "TSCWrap";
>> + case BlockVerifier::State::CustomEvent:
>> + return "CustomEvent";
>> + case BlockVerifier::State::Function:
>> + return "Function";
>> + case BlockVerifier::State::CallArg:
>> + return "CallArg";
>> + case BlockVerifier::State::EndOfBuffer:
>> + return "EndOfBuffer";
>> + case BlockVerifier::State::StateMax:
>> + case BlockVerifier::State::Unknown:
>> + return "Unknown";
>> + }
>> +}
>> +
>> +} // namespace
>> +
>> +Error BlockVerifier::transition(State To) {
>> + using ToSet = std::bitset<number(State::StateMax)>;
>> + static constexpr std::array<const std::tuple<State, ToSet>,
>> + number(State::StateMax)>
>> + TransitionTable{{{State::Unknown,
>> + {mask(State::BufferExtents) | mask(State::NewBuffer)}},
>> +
>> + {State::BufferExtents, {mask(State::NewBuffer)}},
>> +
>> + {State::NewBuffer, {mask(State::WallClockTime)}},
>> +
>> + {State::WallClockTime,
>> + {mask(State::PIDEntry) | mask(State::NewCPUId)}},
>> +
>> + {State::PIDEntry, {mask(State::NewCPUId)}},
>> +
>> + {State::NewCPUId,
>> + {mask(State::NewCPUId) | mask(State::TSCWrap) |
>> + mask(State::CustomEvent) | mask(State::Function) |
>> + mask(State::EndOfBuffer)}},
>> +
>> + {State::TSCWrap,
>> + {mask(State::TSCWrap) | mask(State::NewCPUId) |
>> + mask(State::CustomEvent) | mask(State::Function) |
>> + mask(State::EndOfBuffer)}},
>> +
>> + {State::CustomEvent,
>> + {mask(State::CustomEvent) | mask(State::TSCWrap) |
>> + mask(State::NewCPUId) | mask(State::Function) |
>> + mask(State::EndOfBuffer)}},
>> +
>> + {State::Function,
>> + {mask(State::Function) | mask(State::TSCWrap) |
>> + mask(State::NewCPUId) | mask(State::CustomEvent) |
>> + mask(State::CallArg) | mask(State::EndOfBuffer)}},
>> +
>> + {State::CallArg,
>> + {mask(State::CallArg) | mask(State::Function) |
>> + mask(State::TSCWrap) | mask(State::NewCPUId) |
>> + mask(State::CustomEvent) | mask(State::EndOfBuffer)}},
>> +
>> + {State::EndOfBuffer, {}}}};
>> +
>> + if (CurrentRecord >= State::StateMax)
>> + return createStringError(
>> + std::make_error_code(std::errc::executable_format_error),
>> + "BUG (BlockVerifier): Cannot find transition table entry for %s, "
>> + "transitioning to %s.",
>> + recordToString(CurrentRecord).data(), recordToString(To).data());
>> +
>> + // If we're at an EndOfBuffer record, we ignore anything that follows that
>> + // isn't a NewBuffer record.
>> + if (CurrentRecord == State::EndOfBuffer && To != State::NewBuffer)
>> + return Error::success();
>> +
>> + auto &Mapping = TransitionTable[number(CurrentRecord)];
>> + auto &From = std::get<0>(Mapping);
>> + auto &Destinations = std::get<1>(Mapping);
>> + assert(From == CurrentRecord && "BUG: Wrong index for record mapping.");
>> + if ((Destinations & ToSet(mask(To))) == 0)
>> + return createStringError(
>> + std::make_error_code(std::errc::executable_format_error),
>> + "BlockVerifier: Invalid transition from %s to %s.",
>> + recordToString(CurrentRecord).data(), recordToString(To).data());
>> +
>> + CurrentRecord = To;
>> + return Error::success();
>> +} // namespace xray
>> +
>> +Error BlockVerifier::visit(BufferExtents &) {
>> + return transition(State::BufferExtents);
>> +}
>> +
>> +Error BlockVerifier::visit(WallclockRecord &) {
>> + return transition(State::WallClockTime);
>> +}
>> +
>> +Error BlockVerifier::visit(NewCPUIDRecord &) {
>> + return transition(State::NewCPUId);
>> +}
>> +
>> +Error BlockVerifier::visit(TSCWrapRecord &) {
>> + return transition(State::TSCWrap);
>> +}
>> +
>> +Error BlockVerifier::visit(CustomEventRecord &) {
>> + return transition(State::CustomEvent);
>> +}
>> +
>> +Error BlockVerifier::visit(CallArgRecord &) {
>> + return transition(State::CallArg);
>> +}
>> +
>> +Error BlockVerifier::visit(PIDRecord &) { return transition(State::PIDEntry); }
>> +
>> +Error BlockVerifier::visit(NewBufferRecord &) {
>> + return transition(State::NewBuffer);
>> +}
>> +
>> +Error BlockVerifier::visit(EndBufferRecord &) {
>> + return transition(State::EndOfBuffer);
>> +}
>> +
>> +Error BlockVerifier::visit(FunctionRecord &) {
>> + return transition(State::Function);
>> +}
>> +
>> +Error BlockVerifier::verify() {
>> + // The known terminal conditions are the following:
>> + switch (CurrentRecord) {
>> + case State::EndOfBuffer:
>> + case State::NewCPUId:
>> + case State::CustomEvent:
>> + case State::Function:
>> + case State::CallArg:
>> + case State::TSCWrap:
>> + return Error::success();
>> + default:
>> + return createStringError(
>> + std::make_error_code(std::errc::executable_format_error),
>> + "BlockVerifier: Invalid terminal condition %s, malformed block.",
>> + recordToString(CurrentRecord).data());
>> + }
>> +}
>> +
>> +void BlockVerifier::reset() { CurrentRecord = State::Unknown; }
>> +
>> +} // namespace xray
>> +} // namespace llvm
>>
>> Modified: llvm/trunk/lib/XRay/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/XRay/CMakeLists.txt?rev=341628&r1=341627&r2=341628&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/XRay/CMakeLists.txt (original)
>> +++ llvm/trunk/lib/XRay/CMakeLists.txt Thu Sep 6 19:25:06 2018
>> @@ -1,5 +1,6 @@
>> add_llvm_library(LLVMXRay
>> BlockIndexer.cpp
>> + BlockVerifier.cpp
>> FDRRecordProducer.cpp
>> FDRRecords.cpp
>> FDRTraceWriter.cpp
>>
>> Modified: llvm/trunk/unittests/XRay/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/XRay/CMakeLists.txt?rev=341628&r1=341627&r2=341628&view=diff
>> ==============================================================================
>> --- llvm/trunk/unittests/XRay/CMakeLists.txt (original)
>> +++ llvm/trunk/unittests/XRay/CMakeLists.txt Thu Sep 6 19:25:06 2018
>> @@ -1,11 +1,13 @@
>> set(LLVM_LINK_COMPONENTS
>> Support
>> XRay
>> + TestingSupport
>> )
>>
>> add_llvm_unittest(XRayTests
>> ProfileTest.cpp
>> FDRBlockIndexerTest.cpp
>> + FDRBlockVerifierTest.cpp
>> FDRProducerConsumerTest.cpp
>> FDRRecordPrinterTest.cpp
>> FDRTraceWriterTest.cpp
>>
>> Added: llvm/trunk/unittests/XRay/FDRBlockVerifierTest.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/XRay/FDRBlockVerifierTest.cpp?rev=341628&view=auto
>> ==============================================================================
>> --- llvm/trunk/unittests/XRay/FDRBlockVerifierTest.cpp (added)
>> +++ llvm/trunk/unittests/XRay/FDRBlockVerifierTest.cpp Thu Sep 6 19:25:06 2018
>> @@ -0,0 +1,139 @@
>> +//===- llvm/unittest/XRay/FDRBlockVerifierTest.cpp --------------*- C++ -*-===//
>> +//
>> +// The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +#include "llvm/Testing/Support/Error.h"
>> +#include "llvm/XRay/BlockIndexer.h"
>> +#include "llvm/XRay/BlockVerifier.h"
>> +#include "llvm/XRay/FDRLogBuilder.h"
>> +#include "llvm/XRay/FDRRecords.h"
>> +#include "gmock/gmock.h"
>> +#include "gtest/gtest.h"
>> +
>> +namespace llvm {
>> +namespace xray {
>> +namespace {
>> +
>> +using ::testing::ElementsAre;
>> +using ::testing::Not;
>> +using ::testing::SizeIs;
>> +
>> +TEST(FDRBlockVerifierTest, ValidBlocksV3) {
>> + auto Block0 = LogBuilder()
>> + .add<BufferExtents>(80)
>> + .add<NewBufferRecord>(1)
>> + .add<WallclockRecord>(1, 2)
>> + .add<PIDRecord>(1)
>> + .add<NewCPUIDRecord>(1)
>> + .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
>> + .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
>> + .consume();
>> + auto Block1 = LogBuilder()
>> + .add<BufferExtents>(80)
>> + .add<NewBufferRecord>(1)
>> + .add<WallclockRecord>(1, 2)
>> + .add<PIDRecord>(1)
>> + .add<NewCPUIDRecord>(1)
>> + .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
>> + .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
>> + .consume();
>> + auto Block2 = LogBuilder()
>> + .add<BufferExtents>(80)
>> + .add<NewBufferRecord>(2)
>> + .add<WallclockRecord>(1, 2)
>> + .add<PIDRecord>(1)
>> + .add<NewCPUIDRecord>(2)
>> + .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
>> + .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
>> + .consume();
>> + BlockIndexer::Index Index;
>> + BlockIndexer Indexer(Index);
>> + for (auto B : {std::ref(Block0), std::ref(Block1), std::ref(Block2)}) {
>> + for (auto &R : B.get())
>> + ASSERT_FALSE(errorToBool(R->apply(Indexer)));
>> + ASSERT_FALSE(errorToBool(Indexer.flush()));
>> + }
>> +
>> + BlockVerifier Verifier;
>> + for (auto &ProcessThreadBlocks : Index) {
>> + auto &Blocks = ProcessThreadBlocks.second;
>> + for (auto &B : Blocks) {
>> + for (auto *R : B.Records)
>> + ASSERT_FALSE(errorToBool(R->apply(Verifier)));
>> + ASSERT_FALSE(errorToBool(Verifier.verify()));
>> + Verifier.reset();
>> + }
>> + }
>> +}
>> +
>> +TEST(FDRBlockVerifierTest, MissingPIDRecord) {
>> + auto Block = LogBuilder()
>> + .add<BufferExtents>(20)
>> + .add<NewBufferRecord>(1)
>> + .add<WallclockRecord>(1, 2)
>> + .add<NewCPUIDRecord>(1)
>> + .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
>> + .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
>> + .consume();
>> + BlockVerifier Verifier;
>> + for (auto &R : Block)
>> + ASSERT_FALSE(errorToBool(R->apply(Verifier)));
>> + ASSERT_FALSE(errorToBool(Verifier.verify()));
>> +}
>> +
>> +TEST(FDRBlockVerifierTest, MissingBufferExtents) {
>> + auto Block = LogBuilder()
>> + .add<NewBufferRecord>(1)
>> + .add<WallclockRecord>(1, 2)
>> + .add<NewCPUIDRecord>(1)
>> + .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
>> + .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
>> + .consume();
>> + BlockVerifier Verifier;
>> + for (auto &R : Block)
>> + ASSERT_FALSE(errorToBool(R->apply(Verifier)));
>> + ASSERT_FALSE(errorToBool(Verifier.verify()));
>> +}
>> +
>> +TEST(FDRBlockVerifierTest, IgnoreRecordsAfterEOB) {
>> + auto Block = LogBuilder()
>> + .add<NewBufferRecord>(1)
>> + .add<WallclockRecord>(1, 2)
>> + .add<NewCPUIDRecord>(1)
>> + .add<EndBufferRecord>()
>> + .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
>> + .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
>> + .consume();
>> + BlockVerifier Verifier;
>> + for (auto &R : Block)
>> + ASSERT_FALSE(errorToBool(R->apply(Verifier)));
>> + ASSERT_FALSE(errorToBool(Verifier.verify()));
>> +}
>> +
>> +TEST(FDRBlockVerifierTest, MalformedV2) {
>> + auto Block = LogBuilder()
>> + .add<NewBufferRecord>(1)
>> + .add<WallclockRecord>(1, 2)
>> + .add<NewCPUIDRecord>(1)
>> + .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
>> + .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
>> + .add<NewBufferRecord>(2)
>> + .consume();
>> + BlockVerifier Verifier;
>> +
>> + ASSERT_THAT(Block, SizeIs(6u));
>> + EXPECT_THAT_ERROR(Block[0]->apply(Verifier), Succeeded());
>> + EXPECT_THAT_ERROR(Block[1]->apply(Verifier), Succeeded());
>> + EXPECT_THAT_ERROR(Block[2]->apply(Verifier), Succeeded());
>> + EXPECT_THAT_ERROR(Block[3]->apply(Verifier), Succeeded());
>> + EXPECT_THAT_ERROR(Block[4]->apply(Verifier), Succeeded());
>> + EXPECT_THAT_ERROR(Block[5]->apply(Verifier), Failed());
>> +}
>> +
>> +} // 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
More information about the llvm-commits
mailing list