123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- //===- BlockVerifier.cpp - FDR Block Verifier -----------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #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::TypedEvent:
- return "TypedEvent";
- case BlockVerifier::State::StateMax:
- case BlockVerifier::State::Unknown:
- return "Unknown";
- }
- llvm_unreachable("Unkown state!");
- }
- struct Transition {
- BlockVerifier::State From;
- std::bitset<number(BlockVerifier::State::StateMax)> ToStates;
- };
- } // namespace
- Error BlockVerifier::transition(State To) {
- using ToSet = std::bitset<number(State::StateMax)>;
- static constexpr std::array<const Transition, 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) | mask(State::TypedEvent)}},
- {State::TSCWrap,
- {mask(State::TSCWrap) | mask(State::NewCPUId) |
- mask(State::CustomEvent) | mask(State::Function) |
- mask(State::EndOfBuffer) | mask(State::TypedEvent)}},
- {State::CustomEvent,
- {mask(State::CustomEvent) | mask(State::TSCWrap) |
- mask(State::NewCPUId) | mask(State::Function) |
- mask(State::EndOfBuffer) | mask(State::TypedEvent)}},
- {State::TypedEvent,
- {mask(State::TypedEvent) | mask(State::TSCWrap) |
- mask(State::NewCPUId) | mask(State::Function) |
- mask(State::EndOfBuffer) | mask(State::CustomEvent)}},
- {State::Function,
- {mask(State::Function) | mask(State::TSCWrap) |
- mask(State::NewCPUId) | mask(State::CustomEvent) |
- mask(State::CallArg) | mask(State::EndOfBuffer) |
- mask(State::TypedEvent)}},
- {State::CallArg,
- {mask(State::CallArg) | mask(State::Function) |
- mask(State::TSCWrap) | mask(State::NewCPUId) |
- mask(State::CustomEvent) | mask(State::EndOfBuffer) |
- mask(State::TypedEvent)}},
- {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 &Destinations = Mapping.ToStates;
- assert(Mapping.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(CustomEventRecordV5 &) {
- return transition(State::CustomEvent);
- }
- Error BlockVerifier::visit(TypedEventRecord &) {
- return transition(State::TypedEvent);
- }
- 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::TypedEvent:
- 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
|