/*
 * 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/SkSLVarDeclarations.h"

#include "include/sksl/SkSLErrorReporter.h"
#include "src/sksl/SkSLAnalysis.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/SkSLThreadContext.h"

namespace SkSL {


std::unique_ptr<Statement> VarDeclaration::clone() const {
    // Cloning a VarDeclaration is inherently problematic, as we normally expect a one-to-one
    // mapping between Variables and VarDeclarations and a straightforward clone would violate this
    // assumption. We could of course theoretically clone the Variable as well, but that would
    // require additional context and tracking, since for the whole process to work we would also
    // have to fixup any subsequent VariableReference clones to point to the newly cloned Variables
    // instead of the originals.
    //
    // Since the only reason we ever clone VarDeclarations is to support tests of clone() and we do
    // not expect to ever need to do so otherwise, a full solution to this issue is unnecessary at
    // the moment. We instead just keep track of whether a VarDeclaration is a clone so we can
    // handle its cleanup properly. This allows clone() to work in the simple case that a
    // VarDeclaration's clone does not outlive the original, which is adequate for testing. Since
    // this leaves a sharp  edge in place - destroying the original could cause a use-after-free in
    // some circumstances - we also disable cloning altogether unless the
    // fAllowVarDeclarationCloneForTesting ProgramSetting is enabled.
    if (ThreadContext::Settings().fAllowVarDeclarationCloneForTesting) {
        return std::make_unique<VarDeclaration>(&this->var(),
                                                &this->baseType(),
                                                fArraySize,
                                                this->value() ? this->value()->clone() : nullptr,
                                                /*isClone=*/true);
    } else {
        SkDEBUGFAIL("VarDeclaration::clone() is unsupported");
        return nullptr;
    }
}

std::string VarDeclaration::description() const {
    std::string result = this->var().modifiers().description() + this->baseType().description() +
                         " " + std::string(this->var().name());
    if (this->arraySize() > 0) {
        String::appendf(&result, "[%d]", this->arraySize());
    }
    if (this->value()) {
        result += " = " + this->value()->description();
    }
    result += ";";
    return result;
}

void VarDeclaration::ErrorCheck(const Context& context,
                                Position pos,
                                Position modifiersPosition,
                                const Modifiers& modifiers,
                                const Type* baseType,
                                Variable::Storage storage) {
    SkASSERT(!baseType->isArray());

    if (baseType->matches(*context.fTypes.fInvalid)) {
        context.fErrors->error(pos, "invalid type");
        return;
    }
    if (baseType->isVoid()) {
        context.fErrors->error(pos, "variables of type 'void' are not allowed");
        return;
    }

    if (baseType->componentType().isOpaque() && storage != Variable::Storage::kGlobal) {
        context.fErrors->error(pos,
                "variables of type '" + baseType->displayName() + "' must be global");
    }
    if ((modifiers.fFlags & Modifiers::kIn_Flag) && baseType->isMatrix()) {
        context.fErrors->error(pos, "'in' variables may not have matrix type");
    }
    if ((modifiers.fFlags & Modifiers::kIn_Flag) && (modifiers.fFlags & Modifiers::kUniform_Flag)) {
        context.fErrors->error(pos, "'in uniform' variables not permitted");
    }
    if (ProgramConfig::IsRuntimeEffect(context.fConfig->fKind)) {
        if (modifiers.fFlags & Modifiers::kIn_Flag) {
            context.fErrors->error(pos, "'in' variables not permitted in runtime effects");
        }
        if (modifiers.fFlags & Modifiers::kUniform_Flag) {
            auto validUniformType = [](const Type& t) {
                const Type& ct = t.componentType();
                return t.isEffectChild() ||
                       ((t.isScalar() || t.isVector()) && ct.isSigned() && ct.bitWidth() == 32) ||
                       ((t.isScalar() || t.isVector() || t.isMatrix()) && ct.isFloat());
            };
            if (!validUniformType(*baseType)) {
                context.fErrors->error(
                        pos,
                        "variables of type '" + baseType->displayName() + "' may not be uniform");
            }
        }
    }
    if (baseType->isEffectChild() && !(modifiers.fFlags & Modifiers::kUniform_Flag)) {
        context.fErrors->error(pos,
                "variables of type '" + baseType->displayName() + "' must be uniform");
    }
    if (modifiers.fFlags & Modifiers::kUniform_Flag &&
        (context.fConfig->fKind == ProgramKind::kMeshVertex ||
         context.fConfig->fKind == ProgramKind::kMeshFragment)) {
        context.fErrors->error(pos, "uniforms are not permitted in custom mesh shaders");
    }
    if (modifiers.fLayout.fFlags & Layout::kColor_Flag) {
        if (!ProgramConfig::IsRuntimeEffect(context.fConfig->fKind)) {
            context.fErrors->error(pos, "'layout(color)' is only permitted in runtime effects");
        }
        if (!(modifiers.fFlags & Modifiers::kUniform_Flag)) {
            context.fErrors->error(pos,
                                   "'layout(color)' is only permitted on 'uniform' variables");
        }
        auto validColorXformType = [](const Type& t) {
            return t.isVector() && t.componentType().isFloat() &&
                   (t.columns() == 3 || t.columns() == 4);
        };
        if (!validColorXformType(*baseType)) {
            context.fErrors->error(pos,
                                   "'layout(color)' is not permitted on variables of type '" +
                                           baseType->displayName() + "'");
        }
    }
    int permitted = Modifiers::kConst_Flag | Modifiers::kHighp_Flag | Modifiers::kMediump_Flag |
                    Modifiers::kLowp_Flag;
    if (storage == Variable::Storage::kGlobal) {
        permitted |= Modifiers::kIn_Flag | Modifiers::kOut_Flag | Modifiers::kUniform_Flag |
                     Modifiers::kFlat_Flag | Modifiers::kNoPerspective_Flag;
    }
    // TODO(skbug.com/11301): Migrate above checks into building a mask of permitted layout flags

    int permittedLayoutFlags = ~0;
    // We don't allow 'binding' or 'set' on normal uniform variables, only on textures, samplers,
    // and interface blocks (holding uniform variables). They're also only allowed at global scope,
    // not on interface block fields (or locals/parameters).
    bool permitBindingAndSet = baseType->typeKind() == Type::TypeKind::kSampler ||
                               baseType->typeKind() == Type::TypeKind::kSeparateSampler ||
                               baseType->typeKind() == Type::TypeKind::kTexture ||
                               baseType->isInterfaceBlock();
    if (storage != Variable::Storage::kGlobal ||
        ((modifiers.fFlags & Modifiers::kUniform_Flag) && !permitBindingAndSet)) {
        permittedLayoutFlags &= ~Layout::kBinding_Flag;
        permittedLayoutFlags &= ~Layout::kSet_Flag;
    }
    modifiers.checkPermitted(context, modifiersPosition, permitted, permittedLayoutFlags);
}

bool VarDeclaration::ErrorCheckAndCoerce(const Context& context, const Variable& var,
        std::unique_ptr<Expression>& value) {
    const Type* baseType = &var.type();
    if (baseType->isArray()) {
        baseType = &baseType->componentType();
    }
    ErrorCheck(context, var.fPosition, var.modifiersPosition(), var.modifiers(), baseType,
            var.storage());
    if (value) {
        if (var.type().isOpaque()) {
            context.fErrors->error(value->fPosition, "opaque type '" + var.type().displayName() +
                    "' cannot use initializer expressions");
            return false;
        }
        if (var.modifiers().fFlags & Modifiers::kIn_Flag) {
            context.fErrors->error(value->fPosition,
                                   "'in' variables cannot use initializer expressions");
            return false;
        }
        if (var.modifiers().fFlags & Modifiers::kUniform_Flag) {
            context.fErrors->error(value->fPosition,
                                   "'uniform' variables cannot use initializer expressions");
            return false;
        }
        if (var.storage() == Variable::Storage::kInterfaceBlock) {
            context.fErrors->error(value->fPosition,
                                   "initializers are not permitted on interface block fields");
            return false;
        }
        value = var.type().coerceExpression(std::move(value), context);
        if (!value) {
            return false;
        }
    }
    if (var.modifiers().fFlags & Modifiers::kConst_Flag) {
        if (!value) {
            context.fErrors->error(var.fPosition, "'const' variables must be initialized");
            return false;
        }
        if (!Analysis::IsConstantExpression(*value)) {
            context.fErrors->error(value->fPosition,
                                   "'const' variable initializer must be a constant expression");
            return false;
        }
    }
    if (var.storage() == Variable::Storage::kInterfaceBlock) {
        if (var.type().isOpaque()) {
            context.fErrors->error(var.fPosition, "opaque type '" + var.type().displayName() +
                    "' is not permitted in an interface block");
            return false;
        }
    }
    if (var.storage() == Variable::Storage::kGlobal) {
        if (value && !Analysis::IsConstantExpression(*value)) {
            context.fErrors->error(value->fPosition,
                                   "global variable initializer must be a constant expression");
            return false;
        }
    }
    return true;
}

std::unique_ptr<Statement> VarDeclaration::Convert(const Context& context,
        std::unique_ptr<Variable> var, std::unique_ptr<Expression> value, bool addToSymbolTable) {
    if (!ErrorCheckAndCoerce(context, *var, value)) {
        return nullptr;
    }
    const Type* baseType = &var->type();
    int arraySize = 0;
    if (baseType->isArray()) {
        arraySize = baseType->columns();
        baseType = &baseType->componentType();
    }
    std::unique_ptr<Statement> varDecl = VarDeclaration::Make(context, var.get(), baseType,
            arraySize, std::move(value));
    if (!varDecl) {
        return nullptr;
    }

    // Detect the declaration of magical variables.
    if ((var->storage() == Variable::Storage::kGlobal) && var->name() == Compiler::FRAGCOLOR_NAME) {
        // Silently ignore duplicate definitions of `sk_FragColor`.
        const Symbol* symbol = (*ThreadContext::SymbolTable())[var->name()];
        if (symbol) {
            return nullptr;
        }
    } else if ((var->storage() == Variable::Storage::kGlobal ||
                var->storage() == Variable::Storage::kInterfaceBlock) &&
               var->name() == Compiler::RTADJUST_NAME) {
        // `sk_RTAdjust` is special, and makes the IR generator emit position-fixup expressions.
        if (ThreadContext::RTAdjustState().fVar || ThreadContext::RTAdjustState().fInterfaceBlock) {
            context.fErrors->error(var->fPosition, "duplicate definition of 'sk_RTAdjust'");
            return nullptr;
        }
        if (!var->type().matches(*context.fTypes.fFloat4)) {
            context.fErrors->error(var->fPosition, "sk_RTAdjust must have type 'float4'");
            return nullptr;
        }
        ThreadContext::RTAdjustState().fVar = var.get();
    }

    if (addToSymbolTable) {
        ThreadContext::SymbolTable()->add(std::move(var));
    } else {
        ThreadContext::SymbolTable()->takeOwnershipOfSymbol(std::move(var));
    }
    return varDecl;
}

std::unique_ptr<Statement> VarDeclaration::Make(const Context& context, Variable* var,
        const Type* baseType, int arraySize, std::unique_ptr<Expression> value) {
    SkASSERT(!baseType->isArray());
    // function parameters cannot have variable declarations
    SkASSERT(var->storage() != Variable::Storage::kParameter);
    // 'const' variables must be initialized
    SkASSERT(!(var->modifiers().fFlags & Modifiers::kConst_Flag) || value);
    // 'const' variable initializer must be a constant expression
    SkASSERT(!(var->modifiers().fFlags & Modifiers::kConst_Flag) ||
             Analysis::IsConstantExpression(*value));
    // global variable initializer must be a constant expression
    SkASSERT(!(value && var->storage() == Variable::Storage::kGlobal &&
               !Analysis::IsConstantExpression(*value)));
    // opaque type not permitted on an interface block
    SkASSERT(!(var->storage() == Variable::Storage::kInterfaceBlock && var->type().isOpaque()));
    // initializers are not permitted on interface block fields
    SkASSERT(!(var->storage() == Variable::Storage::kInterfaceBlock && value));
    // opaque type cannot use initializer expressions
    SkASSERT(!(value && var->type().isOpaque()));
    // 'in' variables cannot use initializer expressions
    SkASSERT(!(value && (var->modifiers().fFlags & Modifiers::kIn_Flag)));
    // 'uniform' variables cannot use initializer expressions
    SkASSERT(!(value && (var->modifiers().fFlags & Modifiers::kUniform_Flag)));

    auto result = std::make_unique<VarDeclaration>(var, baseType, arraySize, std::move(value));
    var->setDeclaration(result.get());
    return std::move(result);
}

}  // namespace SkSL
