/*========================== begin_copyright_notice ============================
Copyright (C) 2024-2026 Intel Corporation

SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/

/*!
 * @file A tool that detects uninitialized memory read accesses in kernels
 */

#ifndef MEMORY_CHECK_H_
#define MEMORY_CHECK_H_

#include "hlif_basic_defs.h"

#if defined(__cplusplus)
#include "gtpin_api.h"
using namespace gtpin;
#endif

#pragma pack(push, 8)

#define UNINITIALIZED_MEMORY_PATTERN 0xdeadbeef

/* ============================================================================================= */
// Struct MemoryCheckArgs
/* ============================================================================================= */
/// Common arguments of HLI functions that detects uninitialized memory read accesses
typedef struct MemoryCheckArgs
{
    struct
    {
        uint32_t    numAccesses;   ///< Number of elements accessed by the instruction
        uint32_t    dataSize;      ///< Size, in bytes, of the memory element
    } in;
    struct
    {
        uint32_t    umrCount;     ///< Counter of detected uninitialized memory read accesses
    } out;

    #if defined(__cplusplus)
    /// Constructor
    MemoryCheckArgs() : in({0, 0}), out({0}) {}
    #endif
} MemoryCheckArgs;


/* ============================================================================================= */
// Struct SlmInitArg
/* ============================================================================================= */
/// Argument of HLI function that initializes SLM memory
typedef struct SlmInitArg
{
    struct
    {
        uint32_t    size;  ///< SLM size per working group
    } in;

#if defined(__cplusplus)
    /// Constructor
    SlmInitArg(uint32_t size = 0) : in({size}) {}
#endif
} SlmInitArg;

/* ============================================================================================= */
// Function CheckReadAccess
/* ============================================================================================= */
/*!
 * @brief HLI function that detects uninitialized memory read accesses
 *        Only accesses that are a multiplication of dword are supported
 * @param[in]       dstPayload          Array of data elements read by the instruction
 * @param[in]       accessMask          Per-channel mask of memory accesses
 * @param[in][out]  memoryCheckArgs     Information about memory access instruction and results of the memory check
 */
IGC_STACK_CALL void CheckReadAccess(__global const uint32_t* dstPayload,
                                    uint32_t accessMask,
                                    __global MemoryCheckArgs* memoryCheckArgs);
#if defined(__cplusplus)
using CheckReadAccessFunc = GtHliFunction<void, const uint32_t*, uint32_t, MemoryCheckArgs*>;
#endif

/*!
 * @brief HLI function that detects uninitialized Shared Local Memory read accesses
 *        Only accesses that are a multiplication of dword are supported
 * @param[in]       offsets             Array of offsets into SLM memory
 * @param[in]       accessMask          Per-channel mask of memory accesses
 * @param[in][out]  memoryCheckArgs     Information about memory access instruction and results of the memory check
 * @param[in]       slm                 Pointer to the local memory
 */
IGC_STACK_CALL void CheckSlmReadAccess(__global const uint32_t* offsets,
                                       uint32_t accessMask,
                                       __global MemoryCheckArgs* memoryCheckArgs,
                                       __local uint32_t* slm);
#if defined(__cplusplus)
using CheckSlmReadAccessFunc = GtHliFunction<void, const uint32_t*, uint32_t, MemoryCheckArgs*, uint32_t>;
#endif

/*!
 * @brief HLI function that detects uninitialized global memory read accesses done in A64 mode
 *        Only accesses that are a multiplication of dword are supported
 * @param[in]       addresses           Array of 64-bit addresses
 * @param[in]       accessMask          Per-channel mask of memory accesses
 * @param[in][out]  memoryCheckArgs     Information about memory access instruction and results of the memory check
 */
IGC_STACK_CALL void CheckUgmA64ReadAccess(__global const uint64_t* addresses,
                                          uint32_t accessMask,
                                          __global MemoryCheckArgs* memoryCheckArgs);

#if defined(__cplusplus)
    using CheckUgmA64ReadAccessFunc = GtHliFunction<void, const uint64_t*, uint32_t, MemoryCheckArgs*>;
#endif

/*!
 * @brief HLI function that initializes shared local memory
 * @param[in]  arg     Information about SLM memory
 * @param[in]  slm     Pointer to the local memory
 */
void InitSlm(__global const SlmInitArg* arg, __local uint32_t* slm);

#if defined(__cplusplus)
using InitSlmFunc = GtHliFunction<void, const SlmInitArg*, uint32_t>;
#endif

#pragma pack(pop)

#endif