/*
 * Copyright (C) 2015 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 "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:
    // 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,
    };

    // 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,
        LABEL       = 14,
    };

    // General signature for functions callable by the interpreter with a function call instruction.
    // The first argument is a pointer to the stack of the Virtual Machine and the second argument
    // is true if the caller expect the return value of the function to be pushed to the stack. The
    // function should return true if the function call was successful, false otherwise
    typedef std::function<bool(Stack*, bool)> Function;

    // 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);

    // Register a new function for the specific opcode
    void registerFunction(uint16_t opcode, Function function);

    // 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,
        PUSH_RETURN_MASK = 0x01000000U,
        DATA_MASK20      = 0x000fffffU,
        DATA_MASK26      = 0x03ffffffU,
        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 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 stack of the Virtual Machine
    Stack mStack;

    // Map of the supported function ids to the actual function implementations
    std::unordered_map<uint16_t, Function> mFunctions;

    // 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
