/*===================== begin_copyright_notice ==================================

Copyright (c) 2017 Intel Corporation

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


======================= end_copyright_notice ==================================*/

#pragma once

#include <stdint.h>
#include <stddef.h>

#if defined(_WIN32)
    // INSIDE_PLUGIN must be defined in the pre-processor definitions of the
    // CTranslationBlock DLL project
    #define TRANSLATION_BLOCK_CALLING_CONV __cdecl
    #ifndef TRANSLATION_BLOCK_API
        #ifdef INSIDE_PLUGIN
            #define TRANSLATION_BLOCK_API __declspec(dllexport)
        #else
            #define TRANSLATION_BLOCK_API __declspec(dllimport)
        #endif
    #endif
#else
#define TRANSLATION_BLOCK_CALLING_CONV
    #ifndef TRANSLATION_BLOCK_API
        #define TRANSLATION_BLOCK_API __attribute__((visibility("default")))
    #endif
#endif

namespace TC
{
static const uint32_t STB_VERSION = 1006UL;
static const uint32_t STB_MAX_ERROR_STRING_SIZE = 1024UL;

// Forward prototyping
struct STB_RegisterArgs;
struct STB_CreateArgs;
class  CTranslationBlock;

extern "C" TRANSLATION_BLOCK_API void TRANSLATION_BLOCK_CALLING_CONV Register(STB_RegisterArgs* pRegisterArgs);
extern "C" TRANSLATION_BLOCK_API CTranslationBlock* TRANSLATION_BLOCK_CALLING_CONV Create(STB_CreateArgs* pCreateArgs);
extern "C" TRANSLATION_BLOCK_API void TRANSLATION_BLOCK_CALLING_CONV Delete(CTranslationBlock* pBlock);

typedef void (TRANSLATION_BLOCK_CALLING_CONV *PFNREGISTER)(STB_RegisterArgs* pRegisterArgs);
typedef CTranslationBlock* (TRANSLATION_BLOCK_CALLING_CONV *PFNCREATE)(STB_CreateArgs* pCreateArgs);
typedef void (TRANSLATION_BLOCK_CALLING_CONV *PFNDELETE)(CTranslationBlock* pBlock);

#undef TRANSLATION_BLOCK_CALLING_CONV

/******************************************************************************\

Enumeration:
    TB_DATA_FORMAT

Description:
    Possible i/o formats for the translation classes

\******************************************************************************/
enum TB_DATA_FORMAT
{
    TB_DATA_FORMAT_UNKNOWN,
    TB_DATA_FORMAT_OCL_TEXT,
    TB_DATA_FORMAT_OCL_BINARY,
    TB_DATA_FORMAT_LLVM_TEXT,
    TB_DATA_FORMAT_LLVM_BINARY,
    TB_DATA_FORMAT_GHAL_TEXT,
    TB_DATA_FORMAT_GHAL_BINARY,
    TB_DATA_FORMAT_DEVICE_TEXT,
    TB_DATA_FORMAT_DEVICE_BINARY,
    TB_DATA_FORMAT_LLVM_ARCHIVE,
    TB_DATA_FORMAT_ELF,
    TB_DATA_FORMAT_RS_LLVM_BINARY,
    TB_DATA_FORMAT_RS_INFO,
    TB_DATA_FORMAT_SPIR_V,
    TB_DATA_FORMAT_COHERENT_DEVICE_BINARY,
    TB_DATA_FORMAT_NON_COHERENT_DEVICE_BINARY,
    NUM_TB_DATA_FORMATS
};

/******************************************************************************\

Structure:
    STB_TranslationCode

Description:
    Structure used to describe the requested translation type

\******************************************************************************/
union STB_TranslationCode
{
    struct
    {
        TB_DATA_FORMAT Input  : 16;
        TB_DATA_FORMAT Output : 16;
    }Type;

    uint32_t Code;
};

/******************************************************************************\

Structure:
    STB_CreateArgs

Description:
    Structure used to store arguments used to pass data to the Create function

\******************************************************************************/
struct STB_CreateArgs
{
    //INFO keep two first fields in this order ! for version ICBE 1003 compatibility
    STB_TranslationCode TranslationCode;
    void*               pCreateData;

    STB_CreateArgs()
    {
        TranslationCode.Code = 0;
        pCreateData = NULL;
    }
};

/******************************************************************************\

Structure:
    STB_RegisterArgs

Description:
    Structure containing a pointer to an array of supported translation codes
    and a variable informing us of the size of the translation code array.

    The calling function is responsible for deleting the memory allocated
    for the translation code array.

Note:
    Version is contained in this header

\******************************************************************************/
struct STB_RegisterArgs
{
    uint32_t                 Version;
    uint32_t                 NumTranslationCodes;
    STB_TranslationCode*     pTranslationCodes;

    STB_RegisterArgs()
    {
        Version = STB_VERSION;
        NumTranslationCodes = 0;
        pTranslationCodes = NULL;
    }
};

/******************************************************************************\

Structure:
    STB_TranslateInputArgs

Description:
    Structure used to pass input variables to the translation block

\******************************************************************************/
struct STB_TranslateInputArgs
{
    char*           pInput;               // data to be translated
    uint32_t        InputSize;            // size of data to be translated
    const char*     pOptions;             // list of build/compile options
    uint32_t        OptionsSize;          // size of options list
    const char*     pInternalOptions;     // list of build/compile options
    uint32_t        InternalOptionsSize;  // size of options list
    void*           pTracingOptions;      // instrumentation options
    uint32_t        TracingOptionsCount;  // number of instrumentation options
    void*           GTPinInput;           // input structure for GTPin requests
    bool            CompileTimeStatisticsEnable;
    const uint32_t* pSpecConstantsIds;    // user-defined spec constants ids
    const uint64_t* pSpecConstantsValues; // spec constants values to be translated
    uint32_t        SpecConstantsSize;    // number of specialization constants

    STB_TranslateInputArgs()
    {
        pInput                = NULL;
        InputSize             = 0;
        pOptions              = NULL;
        OptionsSize           = 0;
        pInternalOptions      = NULL;
        InternalOptionsSize   = 0;
        pTracingOptions       = NULL;
        TracingOptionsCount   = 0;
        GTPinInput            = NULL;
        CompileTimeStatisticsEnable = false;
        pSpecConstantsIds     = NULL;
        pSpecConstantsValues  = NULL;
        SpecConstantsSize     = 0;
    }
};

/******************************************************************************\

Structure:
    STB_TranslateOutputArgs

Description:
    Structure used to hold data returned from the translation block

\******************************************************************************/
struct STB_TranslateOutputArgs
{
    char*       pOutput;            // pointer to translated data buffer
    uint32_t    OutputSize;         // translated data buffer size (bytes)
    char*       pErrorString;       // string to print if translate fails
    uint32_t    ErrorStringSize;    // size of error string
    char*       pDebugData;         // pointer to translated debug data buffer
    uint32_t    DebugDataSize;      // translated debug data data size (bytes)

    STB_TranslateOutputArgs()
    {
        pOutput             = NULL;
        OutputSize          = 0;
        pErrorString        = NULL;
        ErrorStringSize     = 0;
        pDebugData          = NULL;
        DebugDataSize       = 0;
    }
};

struct TranslationBlockVersion
{
    static const uint32_t VersioningIsUnsupported = (uint32_t)-1;
    uint32_t TBVersion;   // STB_VERSION version of this translation block
    uint32_t BuildId;     // build ID (for CI builds) of this translation block
};

/******************************************************************************\
Class:
    CTranslationBlock

Description:
    Interface used to expose required functions to translation plug-ins
\******************************************************************************/
class CTranslationBlock
{
public:
    virtual bool Translate(
        const STB_TranslateInputArgs* pInput,
        STB_TranslateOutputArgs* pOutput ) = 0;

    virtual bool FreeAllocations( STB_TranslateOutputArgs* pOutput ) = 0;

    virtual bool GetOpcodes( void* pOpcodes, uint32_t pOpcodesSize ) { return false; }
    virtual bool GetOpcodesCount( uint32_t* pOpcodesCount, uint32_t* pOpcodeSize ){ return false; }
    virtual TranslationBlockVersion GetVersion() const {
        TranslationBlockVersion tbv;
        tbv.TBVersion = TC::STB_VERSION;
        uint32_t buildId = TranslationBlockVersion::VersioningIsUnsupported;
#ifdef TB_BUILD_ID
        buildId = TB_BUILD_ID;
#endif
        tbv.BuildId = buildId;

        return tbv;
    }
    virtual ~CTranslationBlock() {}
};
} // namespace TC
