/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SRC_TRACE_PROCESSOR_CORE_INTERPRETER_BYTECODE_REGISTERS_H_
#define SRC_TRACE_PROCESSOR_CORE_INTERPRETER_BYTECODE_REGISTERS_H_

#include <cstdint>
#include <limits>
#include <memory>
#include <variant>

#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/flat_hash_map.h"
#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/core/common/storage_types.h"
#include "src/trace_processor/core/interpreter/interpreter_types.h"
#include "src/trace_processor/core/util/bit_vector.h"
#include "src/trace_processor/core/util/range.h"
#include "src/trace_processor/core/util/slab.h"
#include "src/trace_processor/core/util/span.h"

namespace perfetto::trace_processor::core::interpreter {

// Register system for the bytecode interpreter.
// Provides typed handles for accessing virtual registers with appropriate
// read/write permissions.

// Base class for all register handle types with common index field.
struct HandleBase {
  uint32_t index = std::numeric_limits<uint32_t>::max();
};

// Handle for read-write registers of type T.
template <typename T>
struct RwHandle : HandleBase {
  RwHandle() = default;
  explicit RwHandle(uint32_t _index) : HandleBase{_index} {}

#if !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC)
  static constexpr bool VerifyPreconditions() {
    static_assert(std::is_trivial_v<RwHandle<T>>);
    static_assert(sizeof(RwHandle<T>) == sizeof(uint32_t));
    return true;
  }
  static constexpr bool kPreconditions = VerifyPreconditions();
#endif
};

// Handle for read-only registers of type T.
template <typename T>
struct ReadHandle : HandleBase {
#if !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC)
  static constexpr bool VerifyPreconditions() {
    static_assert(std::is_trivial_v<ReadHandle<T>>);
    static_assert(sizeof(ReadHandle<T>) == sizeof(uint32_t));
    return true;
  }
  static constexpr bool kPreconditions = VerifyPreconditions();
#endif
  ReadHandle() = default;
  ReadHandle(RwHandle<T> _index) : HandleBase{_index.index} {}
  explicit ReadHandle(uint32_t _index) : HandleBase{_index} {}
};

// Handle for write-only registers of type T.
template <typename T>
struct WriteHandle : HandleBase {
#if !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC)
  static constexpr bool VerifyPreconditions() {
    static_assert(std::is_trivial_v<WriteHandle<T>>);
    static_assert(sizeof(WriteHandle<T>) == sizeof(uint32_t));
    return true;
  }
  static constexpr bool kPreconditions = VerifyPreconditions();
#endif
  WriteHandle() = default;
  WriteHandle(RwHandle<T> _index) : HandleBase{_index.index} {}
  explicit WriteHandle(uint32_t _index) : HandleBase{_index} {}
};

// Empty placeholder type for register values.
struct Empty {};

using StringIdToRankMap =
    std::unique_ptr<base::FlatHashMap<StringPool::Id, uint32_t>>;

// Pointer to storage data along with its type.
struct StoragePtr {
  const void* ptr;
  StorageType type;
};

// Wraps a null bitvector and its prefix popcount cache as a single unit.
// Used for both SparseNull and DenseNull columns:
//  - SparseNull: both |bv| and |popcount| are populated (popcount is lazily
//    computed by the PrefixPopcount bytecode).
//  - DenseNull: only |bv| is populated; |popcount| remains empty.
//  - NonNull: the register handle is empty (UINT32_MAX index), so the struct
//    is never read.
struct NullBitvector {
  const BitVector* bv = nullptr;
  Slab<uint32_t> popcount;
};

// Values that can be stored in a register.
using RegValue = std::variant<Empty,
                              Range,
                              Slab<uint32_t>,
                              Span<uint32_t>,
                              CastFilterValueResult,
                              std::unique_ptr<CastFilterValueListResult>,
                              Slab<uint8_t>,
                              StringIdToRankMap,
                              StoragePtr,
                              const BitVector*,
                              Span<const uint32_t>,
                              BitVector,
                              std::unique_ptr<TreeState>,
                              NullBitvector>;

}  // namespace perfetto::trace_processor::core::interpreter

#endif  // SRC_TRACE_PROCESSOR_CORE_INTERPRETER_BYTECODE_REGISTERS_H_
