/*
 * Copyright (C) 2016 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 GAPIR_INTERPRETER_H
#define GAPIR_INTERPRETER_H

#include "function_table.h"
#include "stack.h"

#include <stdint.h>

#include <functional>
#include <unordered_map>
#include <utility>

namespace gapir {

class MemoryManager;

// Implementation of a (fix sized) stack based virtual machine to interpret the instructions in the
// given opcode stream.
//
// The list of supported opcodes and their detailed definition is described in the
// Interpreter_doc.txt documentation file
class Interpreter {
public:
    // The type of the callback function for requesting to register an api's renderer functions to
    // this interpreter. Taking in the pointer for the interpreter and the api index, the callback
    // is expected to populate the renderer function for the given api index in the interpreter.
    // It should return true if the request is fulfilled.
    using ApiRequestCallback = std::function<bool(Interpreter*, uint8_t)>;

    // Function ids for implementation specific functions and special debugging functions. These
    // functions shouldn't be called by the opcode stream
    enum FunctionIds : uint16_t {
        // Custom function Ids
        POST_FUNCTION_ID        = 0xff00,
        RESOURCE_FUNCTION_ID    = 0xff01,
        // Debug function Ids
        PRINT_STACK_FUNCTION_ID = 0xff80,
        // 0xff81..0xffff reserved for synthetic functions
    };

    // Instruction codes for the different instructions. The codes have to be consistent with the
    // codes on the server side.
    enum class InstructionCode : uint8_t {
        CALL        = 0,
        PUSH_I      = 1,
        LOAD_C      = 2,
        LOAD_V      = 3,
        LOAD        = 4,
        POP         = 5,
        STORE_V     = 6,
        STORE       = 7,
        RESOURCE    = 8,
        POST        = 9,
        COPY        = 10,
        CLONE       = 11,
        STRCPY      = 12,
        EXTEND      = 13,
        ADD         = 14,
        LABEL       = 15,
    };

    // Creates a new interpreter with the specified memory manager (for resolving memory addresses)
    // and with the specified maximum stack size
    Interpreter(const MemoryManager* memoryManager, uint32_t stackDepth,
                ApiRequestCallback callback);

    // Registers a builtin function to the builtin function table.
    void registerBuiltin(FunctionTable::Id, FunctionTable::Function);

    // Assigns the function table as the renderer functions to use for the given api.
    void setRendererFunctions(uint8_t api, FunctionTable* functionTable);

    // Runs the interpreter on the instruction list specified by the pointer and by its size.
    bool run(const std::pair<const uint32_t*, uint32_t>& instructions);

private:
    enum : uint32_t {
        TYPE_MASK        = 0x03f00000U,
        FUNCTION_ID_MASK = 0x0000ffffU,
        API_INDEX_MASK   = 0x000f0000U,
        PUSH_RETURN_MASK = 0x01000000U,
        DATA_MASK20      = 0x000fffffU,
        DATA_MASK26      = 0x03ffffffU,
        API_BIT_SHIFT    = 16,
        TYPE_BIT_SHIFT   = 20,
        OPCODE_BIT_SHIFT = 26,
    };

    // Get type information out from an opcode. The type is always stored in the 7th to 13th MSB
    // (both inclusive) of the opcode
    BaseType extractType(uint32_t opcode) const;

    // Get 20 bit data out from an opcode located in the 20 LSB of the opcode.
    uint32_t extract20bitData(uint32_t opcode) const;

    // Get 26 bit data out from an opcode located in the 26 LSB of the opcode.
    uint32_t extract26bitData(uint32_t opcode) const;

    // Implementation of the opcodes supported by the interpreter. Each function returns true if the
    // operation was successful, false otherwise
    bool call(uint32_t opcode);
    bool pushI(uint32_t opcode);
    bool loadC(uint32_t opcode);
    bool loadV(uint32_t opcode);
    bool load(uint32_t opcode);
    bool pop(uint32_t opcode);
    bool storeV(uint32_t opcode);
    bool store();
    bool resource(uint32_t);
    bool post();
    bool copy(uint32_t opcode);
    bool clone(uint32_t opcode);
    bool strcpy(uint32_t opcode);
    bool extend(uint32_t opcode);
    bool add(uint32_t opcode);
    bool label(uint32_t opcode);

    // Returns true, if address..address+size(type) is "constant" memory.
    bool isConstantAddressForType(const void *address, BaseType type) const;

    // Returns true, if address..address+size(type) is "volatile" memory.
    bool isVolatileAddressForType(const void *address, BaseType type) const;

    // Returns false, if address is known not safe to read from.
    bool isReadAddress(const void * address) const;

    // Returns false, if address is known not safe to write to.
    bool isWriteAddress(void* address) const;

    // Interpret one specific opcode. Returns true if it was successful false otherwise
    bool interpret(uint32_t opcode);

    // Memory manager which managing the memory used during the interpretation
    const MemoryManager* mMemoryManager;

    // The builtin functions.
    FunctionTable mBuiltins;

    // The current renderer functions.
    std::unordered_map<uint8_t, FunctionTable*> mRendererFunctions;

    // Callback function for requesting renderer functions for an unknown api.
    ApiRequestCallback apiRequestCallback;

    // The stack of the Virtual Machine
    Stack mStack;

    // The last reached label value.
    uint32_t mLabel;
};

inline bool Interpreter::isConstantAddressForType(const void *address, BaseType type) const {
    // Treat all pointer types as sizeof(void*)
    size_t size = isPointerType(type) ? sizeof(void*) : baseTypeSize(type);
    return mMemoryManager->isConstantAddressWithSize(address, size);
}

inline bool Interpreter::isVolatileAddressForType(const void *address, BaseType type) const {
    size_t size = isPointerType(type) ? sizeof(void*) : baseTypeSize(type);
    return mMemoryManager->isVolatileAddressWithSize(address, baseTypeSize(type));
}

inline bool Interpreter::isReadAddress(const void * address) const {
    return address != nullptr && !mMemoryManager->isNotObservedAbsoluteAddress(address);
}

inline bool Interpreter::isWriteAddress(void* address) const {
    return address != nullptr &&
            !mMemoryManager->isNotObservedAbsoluteAddress(address) &&
            !mMemoryManager->isConstantAddress(address);
}


}  // namespace gapir

#endif  // GAPIR_INTERPRETER_H
