[llvm] r341628 - [XRay] Add a BlockVerifier visitor for FDR Records
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 6 19:59:22 PDT 2018
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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180906/8beca2e6/attachment.html>
More information about the llvm-commits
mailing list