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

#include "interpreter.h"
#include "memory_manager.h"

#include <gapic/log.h>

#include <utility>
#include <vector>

namespace gapir {

Interpreter::Interpreter(const MemoryManager* memoryManager, uint32_t stackDepth) :
        mMemoryManager(memoryManager), mStack(stackDepth, mMemoryManager),
        mLabel(0) {
    registerFunction(PRINT_STACK_FUNCTION_ID, [](Stack* stack, bool) {
        stack->printStack();
        return true;
    });
}

bool Interpreter::run(const std::pair<const uint32_t*, uint32_t>& instructions) {
    for (uint32_t i = 0; i < instructions.second; ++i) {
        if (!interpret(instructions.first[i])) {
            GAPID_WARNING(
                    "Interpreter stopped because of an interpretation error at opcode %u (%u)\n"
                    "Last reached label: %d\n",
                    i, instructions.first[i], mLabel);
            return false;
        }
    }
    return true;
}

void Interpreter::registerFunction(uint16_t functionCode, Function function) {
    mFunctions[functionCode] = function;
}

BaseType Interpreter::extractType(uint32_t opcode) const {
    return BaseType((opcode & TYPE_MASK) >> TYPE_BIT_SHIFT);
}

uint32_t Interpreter::extract20bitData(uint32_t opcode) const {
    return opcode & DATA_MASK20;
}

uint32_t Interpreter::extract26bitData(uint32_t opcode) const {
    return opcode & DATA_MASK26;
}

bool Interpreter::call(uint32_t opcode) {
    auto func = mFunctions.find(opcode & FUNCTION_ID_MASK);
    if (func == mFunctions.end()) {
        GAPID_WARNING("Invalid function id: %u\n", opcode & FUNCTION_ID_MASK);
        return false;
    } else {
        return func->second(&mStack, (opcode & PUSH_RETURN_MASK) != 0);
    }
}

bool Interpreter::pushI(uint32_t opcode) {
    BaseType type = extractType(opcode);
    if (!isValid(type)) {
        GAPID_WARNING("Error: pushI basic type invalid %u\n", type);
        return false;
    }
    Stack::BaseValue data = extract20bitData(opcode);
    switch (type) {
        // Sign extension for signed types
        case BaseType::Int32:
        case BaseType::Int64:
            if (data & 0x80000) {
                data |= 0xfffffffffff00000ULL;
            }
            break;
        // Shifting the value into the exponent for floating point types
        case BaseType::Float:
            data <<= 23;
            break;
        case BaseType::Double:
            data <<= 52;
            break;
        default:
            break;
    }
    mStack.pushValue(type, data);
    return mStack.isValid();
}

bool Interpreter::loadC(uint32_t opcode) {
    BaseType type = extractType(opcode);
    if (!isValid(type)) {
      GAPID_WARNING("Error: loadC basic type invalid %u\n", type);
      return false;
    }
    const void* address = mMemoryManager->constantToAbsolute(extract20bitData(opcode));
    if (!isConstantAddressForType(address, type)) {
      GAPID_WARNING("Error: loadC not constant address %p\n", address);
      return false;
    }
    mStack.pushFrom(type, address);
    return mStack.isValid();
}

bool Interpreter::loadV(uint32_t opcode) {
    BaseType type = extractType(opcode);
    if (!isValid(type)) {
      GAPID_WARNING("Error: loadV basic type invalid %u\n", type);
      return false;
    }
    const void* address = mMemoryManager->volatileToAbsolute(extract20bitData(opcode));
    if (!isVolatileAddressForType(address, type)) {
      GAPID_WARNING("Error: loadV not volatile address %p\n", address);
      return false;
    }
    mStack.pushFrom(type, address);
    return mStack.isValid();
}

bool Interpreter::load(uint32_t opcode) {
    BaseType type = extractType(opcode);
    if (!isValid(type)) {
      GAPID_WARNING("Error: load basic type invalid %u\n", type);
      return false;
    }
    const void* address = mStack.pop<const void*>();
    if (!isReadAddress(address)) {
      GAPID_WARNING("Error: load not readable address %p\n", address);
      return false;
    }
    mStack.pushFrom(type, address);
    return mStack.isValid();
}

bool Interpreter::pop(uint32_t opcode) {
    mStack.discard(extract26bitData(opcode));
    return mStack.isValid();
}

bool Interpreter::storeV(uint32_t opcode) {
    void* address = mMemoryManager->volatileToAbsolute(extract26bitData(opcode));
    if (!isVolatileAddressForType(address, mStack.getTopType())) {
      GAPID_WARNING("Error: storeV not volatile address %p\n", address);
      return false;
    }

    mStack.popTo(address);
    return mStack.isValid();
}

bool Interpreter::store() {
    void* address = mStack.pop<void*>();
    if (!isWriteAddress(address)) {
      GAPID_WARNING("Error: store not write address %p\n", address);
      return false;
    }
    mStack.popTo(address);
    return mStack.isValid();
}

bool Interpreter::resource(uint32_t opcode) {
    mStack.push<uint32_t>(extract26bitData(opcode));
    return this->call(Interpreter::RESOURCE_FUNCTION_ID);
}

bool Interpreter::post() {
    return this->call(Interpreter::POST_FUNCTION_ID);
}

bool Interpreter::copy(uint32_t opcode) {
    uint32_t count = extract26bitData(opcode);
    void* target = mStack.pop<void*>();
    const void* source = mStack.pop<const void*>();
    if (!isWriteAddress(target)) {
        GAPID_WARNING("Error: copy target is invalid %p %d\n", target, count);
        return false;
    }
    if (!isReadAddress(source)) {
        GAPID_WARNING("Error: copy source is invalid %p %d\n", target, count);
        return false;
    }
    if (source == nullptr) {
        GAPID_WARNING("Error: copy source address is null\n");
        return false;
    }
    if (target == nullptr) {
        GAPID_WARNING("Error: copy destination address is null\n");
        return false;
    }
    memcpy(target, source, count);
    return mStack.isValid();
}

bool Interpreter::clone(uint32_t opcode) {
    mStack.clone(extract26bitData(opcode));
    return mStack.isValid();
}

bool Interpreter::strcpy(uint32_t opcode) {
    uint32_t count = extract26bitData(opcode);
    char* target = mStack.pop<char*>();
    const char* source = mStack.pop<const char*>();
    // Requires that the whole count is available, even if source is shorter.
    if (!isWriteAddress(target)) {
        GAPID_WARNING("Error: copy target is invalid %p %d\n", target, count);
        return false;
    }
    if (!isReadAddress(source)) {
        GAPID_WARNING("Error: copy source is invalid %p %d\n", target, count);
        return false;
    }
    if (source == nullptr) {
        GAPID_WARNING("Error: strcpy source address is null\n");
        return false;
    }
    if (target == nullptr) {
        GAPID_WARNING("Error: strcpy destination address is null\n");
        return false;
    }
    uint32_t i;
    for (i = 0; i < count - 1; i++) {
        char c = source[i];
        if (c == 0) {
            break;
        }
        target[i] = c;
    }
    for (; i < count; i++) {
        target[i] = 0;
    }
    return mStack.isValid();
}

bool Interpreter::extend(uint32_t opcode) {
    uint32_t data = extract26bitData(opcode);
    auto type = mStack.getTopType();
    auto value = mStack.popBaseValue();
    switch (type) {
        // Masking out the mantissa end extending it with the new bits for floating point types
        case BaseType::Float: {
            value |= (data & 0x007fffffULL);
            break;
        }
        case BaseType::Double: {
            uint64_t exponent = value & 0xfff0000000000000ULL;
            value <<= 26;
            value |= data;
            value &= 0x000fffffffffffffULL;
            value |= exponent;
            break;
        }
        // Extending the value with 26 new LSB
        default: {
            value = (value << 26) | data;
            break;
        }
    }
    mStack.pushValue(type, value);
    return mStack.isValid();
}

bool Interpreter::label(uint32_t opcode) {
    mLabel = extract26bitData(opcode);
    return mStack.isValid();
}

#define DEBUG_OPCODE(name, value) GAPID_DEBUG(name "\n")
#define DEBUG_OPCODE_26(name, value) GAPID_DEBUG(name "(%#010x)\n", value & DATA_MASK26)
#define DEBUG_OPCODE_TY_20(name, value) GAPID_DEBUG(name "(%#010x, %s)\n", value & DATA_MASK20, baseTypeName(extractType(value)))

bool Interpreter::interpret(uint32_t opcode) {
    InstructionCode code = static_cast<InstructionCode>(opcode >> OPCODE_BIT_SHIFT);
    switch (code) {
        case InstructionCode::CALL:
            DEBUG_OPCODE_26("CALL", opcode);
            return this->call(opcode);
        case InstructionCode::PUSH_I:
            DEBUG_OPCODE_TY_20("PUSH_I", opcode);
            return this->pushI(opcode);
        case InstructionCode::LOAD_C:
            DEBUG_OPCODE_TY_20("LOAD_C", opcode);
            return this->loadC(opcode);
        case InstructionCode::LOAD_V:
            DEBUG_OPCODE_TY_20("LOAD_V", opcode);
            return this->loadV(opcode);
        case InstructionCode::LOAD:
            DEBUG_OPCODE_TY_20("LOAD", opcode);
            return this->load(opcode);
        case InstructionCode::POP:
            DEBUG_OPCODE_26("POP", opcode);
            return this->pop(opcode);
        case InstructionCode::STORE_V:
            DEBUG_OPCODE_26("STORE_V", opcode);
            return this->storeV(opcode);
        case InstructionCode::STORE:
            DEBUG_OPCODE("STORE", opcode);
            return this->store();
        case InstructionCode::RESOURCE:
            DEBUG_OPCODE_26("RESOURCE", opcode);
            return this->resource(opcode);
        case InstructionCode::POST:
            DEBUG_OPCODE("POST", opcode);
            return this->post();
        case InstructionCode::COPY:
            DEBUG_OPCODE_26("COPY", opcode);
            return this->copy(opcode);
        case InstructionCode::CLONE:
            DEBUG_OPCODE_26("CLONE", opcode);
            return this->clone(opcode);
        case InstructionCode::STRCPY:
            DEBUG_OPCODE_26("STRCPY", opcode);
            return this->strcpy(opcode);
        case InstructionCode::EXTEND:
            DEBUG_OPCODE_26("EXTEND", opcode);
            return this->extend(opcode);
        case InstructionCode::LABEL:
            DEBUG_OPCODE_26("LABEL", opcode);
            return this->label(opcode);
        default:
            GAPID_WARNING("Unknown opcode! %#010x\n", opcode);
            return false;
    }
}

#undef DEBUG_OPCODE

}  // namespace gapir
