/*
 * Copyright 2021 Google LLC.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/sksl/ir/SkSLVariable.h"

#include "include/private/SkSLLayout.h"
#include "include/private/SkStringView.h"
#include "include/sksl/SkSLErrorReporter.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLMangler.h"
#include "src/sksl/SkSLModifiersPool.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLSymbolTable.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"

#include <type_traits>
#include <utility>

namespace SkSL {

Variable::~Variable() {
    // Unhook this Variable from its associated VarDeclaration, since we're being deleted.
    if (fDeclaration) {
        fDeclaration->setVar(nullptr);
    }
}

const Expression* Variable::initialValue() const {
    return fDeclaration ? fDeclaration->value().get() : nullptr;
}

std::string Variable::mangledName() const {
    // Only private variables need to use name mangling.
    std::string_view name = this->name();
    if (!skstd::starts_with(name, '$')) {
        return std::string(name);
    }

    // The $ prefix will fail to compile in GLSL, so replace it with `sk_Priv`.
    name.remove_prefix(1);
    return "sk_Priv" + std::string(name);
}

std::unique_ptr<Variable> Variable::Convert(const Context& context, Position pos,
        Position modifiersPos, const Modifiers& modifiers, const Type* baseType, Position namePos,
        std::string_view name, bool isArray, std::unique_ptr<Expression> arraySize,
        Variable::Storage storage) {
    if (modifiers.fLayout.fLocation == 0 && modifiers.fLayout.fIndex == 0 &&
        (modifiers.fFlags & Modifiers::kOut_Flag) &&
        ProgramConfig::IsFragment(context.fConfig->fKind) && name != Compiler::FRAGCOLOR_NAME) {
        context.fErrors->error(modifiersPos,
                "out location=0, index=0 is reserved for sk_FragColor");
    }
    if (!context.fConfig->fIsBuiltinCode && skstd::starts_with(name, '$')) {
        context.fErrors->error(namePos, "name '" + std::string(name) + "' is reserved");
    }
    if (baseType->isUnsizedArray()) {
        if (!ProgramConfig::IsCompute(ThreadContext::Context().fConfig->fKind)) {
            context.fErrors->error(pos, "unsized arrays are not permitted here");
        } else if (storage != Variable::Storage::kGlobal) {
            context.fErrors->error(pos, "unsized arrays must be global");
        } else if (!(modifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kOut_Flag))) {
            context.fErrors->error(pos, "unsized arrays must be declared 'in' and/or 'out'");
        }
    }
    if (ProgramConfig::IsCompute(ThreadContext::Context().fConfig->fKind) &&
            modifiers.fLayout.fBuiltin == -1) {
        if (storage == Variable::Storage::kGlobal &&
                (modifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kOut_Flag))) {
            if (baseType->typeKind() != Type::TypeKind::kTexture && !baseType->isArray() &&
                    !isArray) {
                context.fErrors->error(pos, "unsupported compute shader in / out type");
            }
            if (baseType->typeKind() != Type::TypeKind::kTexture &&
                    (modifiers.fLayout.fBinding == -1 || modifiers.fLayout.fSet == -1)) {
                context.fErrors->error(pos,
                        "compute shader in / out variables must have a layout binding and set");
            }
        }
    }

    return Make(context, pos, modifiersPos, modifiers, baseType, name, isArray,
            std::move(arraySize), storage);
}

std::unique_ptr<Variable> Variable::Make(const Context& context, Position pos,
        Position modifiersPos, const Modifiers& modifiers, const Type* baseType,
        std::string_view name, bool isArray, std::unique_ptr<Expression> arraySize,
        Variable::Storage storage) {
    const Type* type = baseType;
    int arraySizeValue = 0;
    if (isArray) {
        SkASSERT(arraySize);
        arraySizeValue = type->convertArraySize(context, pos, std::move(arraySize));
        if (!arraySizeValue) {
            return nullptr;
        }
        type = ThreadContext::SymbolTable()->addArrayDimension(type, arraySizeValue);
    }
    return std::make_unique<Variable>(pos, modifiersPos, context.fModifiersPool->add(modifiers),
            name, type, context.fConfig->fIsBuiltinCode, storage);
}

Variable::ScratchVariable Variable::MakeScratchVariable(const Context& context,
                                                        std::string_view baseName,
                                                        const Type* type,
                                                        const Modifiers& modifiers,
                                                        SymbolTable* symbolTable,
                                                        std::unique_ptr<Expression> initialValue) {
    // $floatLiteral or $intLiteral aren't real types that we can use for scratch variables, so
    // replace them if they ever appear here. If this happens, we likely forgot to coerce a type
    // somewhere during compilation.
    if (type->isLiteral()) {
        SkDEBUGFAIL("found a $literal type in MakeScratchVariable");
        type = &type->scalarTypeForLiteral();
    }

    // Out-parameters aren't supported.
    SkASSERT(!(modifiers.fFlags & Modifiers::kOut_Flag));

    // Provide our new variable with a unique name, and add it to our symbol table.
    const std::string* name =
            symbolTable->takeOwnershipOfString(context.fMangler->uniqueName(baseName, symbolTable));

    // Create our new variable and add it to the symbol table.
    ScratchVariable result;
    auto var = std::make_unique<Variable>(initialValue ? initialValue->fPosition : Position(),
                                          /*modifiersPosition=*/Position(),
                                          context.fModifiersPool->add(Modifiers{}),
                                          name->c_str(),
                                          type,
                                          symbolTable->isBuiltin(),
                                          Variable::Storage::kLocal);

    // If we are creating an array type, reduce it to base type plus array-size.
    int arraySize = 0;
    if (type->isArray()) {
        arraySize = type->columns();
        type = &type->componentType();
    }
    // Create our variable declaration.
    result.fVarDecl = VarDeclaration::Make(context, var.get(), type, arraySize,
                                           std::move(initialValue));
    result.fVarSymbol = symbolTable->add(std::move(var));
    return result;
}

} // namespace SkSL
