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

#include "include/private/SkMutex.h"
#include "include/private/SkSLModifiers.h"
#include "include/private/SkSLProgramKind.h"
#include "include/sksl/SkSLPosition.h"
#include "src/sksl/SkSLBuiltinTypes.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLModifiersPool.h"
#include "src/sksl/SkSLModuleLoader.h"
#include "src/sksl/SkSLParsedModule.h"
#include "src/sksl/ir/SkSLSymbolTable.h"
#include "src/sksl/ir/SkSLType.h"
#include "src/sksl/ir/SkSLVariable.h"

#include <type_traits>

#if SKSL_STANDALONE

    // In standalone mode, we load the textual sksl source files. GN generates or copies these files
    // to the skslc executable directory. The "data" in this mode is just the filename.
    #define MODULE_DATA(name) Compiler::MakeModulePath("sksl_" #name ".sksl")

#else

    // At runtime, we load the dehydrated sksl data files. The data is a (pointer, size) pair.
    #include "src/sksl/generated/sksl_shared.dehydrated.sksl"
    #include "src/sksl/generated/sksl_compute.dehydrated.sksl"
    #include "src/sksl/generated/sksl_frag.dehydrated.sksl"
    #include "src/sksl/generated/sksl_gpu.dehydrated.sksl"
    #include "src/sksl/generated/sksl_public.dehydrated.sksl"
    #include "src/sksl/generated/sksl_rt_shader.dehydrated.sksl"
    #include "src/sksl/generated/sksl_vert.dehydrated.sksl"
    #if defined(SK_GRAPHITE_ENABLED)
    #include "src/sksl/generated/sksl_graphite_frag.dehydrated.sksl"
    #include "src/sksl/generated/sksl_graphite_vert.dehydrated.sksl"
    #endif

    #define MODULE_DATA(name) Compiler::MakeModuleData(SKSL_INCLUDE_sksl_##name,\
                                                       SKSL_INCLUDE_sksl_##name##_LENGTH)

#endif

namespace SkSL {

#define TYPE(t) &BuiltinTypes::f ## t

static constexpr BuiltinTypePtr kRootTypes[] = {
    TYPE(Void),

    TYPE( Float), TYPE( Float2), TYPE( Float3), TYPE( Float4),
    TYPE(  Half), TYPE(  Half2), TYPE(  Half3), TYPE(  Half4),
    TYPE(   Int), TYPE(   Int2), TYPE(   Int3), TYPE(   Int4),
    TYPE(  UInt), TYPE(  UInt2), TYPE(  UInt3), TYPE(  UInt4),
    TYPE( Short), TYPE( Short2), TYPE( Short3), TYPE( Short4),
    TYPE(UShort), TYPE(UShort2), TYPE(UShort3), TYPE(UShort4),
    TYPE(  Bool), TYPE(  Bool2), TYPE(  Bool3), TYPE(  Bool4),

    TYPE(Float2x2), TYPE(Float2x3), TYPE(Float2x4),
    TYPE(Float3x2), TYPE(Float3x3), TYPE(Float3x4),
    TYPE(Float4x2), TYPE(Float4x3), TYPE(Float4x4),

    TYPE(Half2x2),  TYPE(Half2x3),  TYPE(Half2x4),
    TYPE(Half3x2),  TYPE(Half3x3),  TYPE(Half3x4),
    TYPE(Half4x2),  TYPE(Half4x3),  TYPE(Half4x4),

    TYPE(SquareMat), TYPE(SquareHMat),
    TYPE(Mat),       TYPE(HMat),

    // TODO(skia:12349): generic short/ushort
    TYPE(GenType),   TYPE(GenIType), TYPE(GenUType),
    TYPE(GenHType),   /* (GenSType)      (GenUSType) */
    TYPE(GenBType),
    TYPE(IntLiteral),
    TYPE(FloatLiteral),

    TYPE(Vec),     TYPE(IVec),     TYPE(UVec),
    TYPE(HVec),    TYPE(SVec),     TYPE(USVec),
    TYPE(BVec),

    TYPE(ColorFilter),
    TYPE(Shader),
    TYPE(Blender),
};

static constexpr BuiltinTypePtr kPrivateTypes[] = {
    TYPE(Sampler2D), TYPE(SamplerExternalOES), TYPE(Sampler2DRect),

    TYPE(SubpassInput), TYPE(SubpassInputMS),

    TYPE(Sampler),
    TYPE(Texture2D),
    TYPE(ReadWriteTexture2D), TYPE(ReadOnlyTexture2D), TYPE(WriteOnlyTexture2D),
    TYPE(GenTexture2D), TYPE(ReadableTexture2D), TYPE(WritableTexture2D),
};

#undef TYPE

struct ModuleLoader::Impl {
    Impl();

    void makeRootSymbolTable();

    // This mutex is taken when ModuleLoader::Get is called, and released when the returned
    // ModuleLoader object falls out of scope.
    SkMutex fMutex;
    const BuiltinTypes fBuiltinTypes;
    ModifiersPool fCoreModifiers;

    ParsedModule fRootModule;
    std::shared_ptr<SymbolTable> fRootSymbolTableWithPublicTypes;

    ParsedModule fSharedModule;              // [Root] + Public intrinsics
    ParsedModule fGPUModule;                 // [Shared] + Non-public intrinsics/helper functions
    ParsedModule fVertexModule;              // [GPU] + Vertex stage decls
    ParsedModule fFragmentModule;            // [GPU] + Fragment stage decls
    ParsedModule fComputeModule;             // [GPU] + Compute stage decls
    ParsedModule fGraphiteVertexModule;      // [Vert] + Graphite vertex helpers
    ParsedModule fGraphiteFragmentModule;    // [Frag] + Graphite fragment helpers

    ParsedModule fPublicModule;              // [Shared] + Runtime effect intrinsics - Private types
    ParsedModule fRuntimeShaderModule;       // [Public] + Runtime shader decls
};

ModuleLoader ModuleLoader::Get() {
    static ModuleLoader::Impl* sModuleLoaderImpl = new ModuleLoader::Impl;
    return ModuleLoader(*sModuleLoaderImpl);
}

ModuleLoader::ModuleLoader(ModuleLoader::Impl& m) : fModuleLoader(m) {
    fModuleLoader.fMutex.acquire();
}

ModuleLoader::~ModuleLoader() {
    fModuleLoader.fMutex.release();
}

ModuleLoader::Impl::Impl() {
    this->makeRootSymbolTable();
}

static void add_public_type_aliases(SkSL::SymbolTable* symbols, const SkSL::BuiltinTypes& types) {
    // Add some aliases to the runtime effect modules so that it's friendlier, and more like GLSL.
    symbols->addWithoutOwnership(types.fVec2.get());
    symbols->addWithoutOwnership(types.fVec3.get());
    symbols->addWithoutOwnership(types.fVec4.get());

    symbols->addWithoutOwnership(types.fIVec2.get());
    symbols->addWithoutOwnership(types.fIVec3.get());
    symbols->addWithoutOwnership(types.fIVec4.get());

    symbols->addWithoutOwnership(types.fBVec2.get());
    symbols->addWithoutOwnership(types.fBVec3.get());
    symbols->addWithoutOwnership(types.fBVec4.get());

    symbols->addWithoutOwnership(types.fMat2.get());
    symbols->addWithoutOwnership(types.fMat3.get());
    symbols->addWithoutOwnership(types.fMat4.get());

    symbols->addWithoutOwnership(types.fMat2x2.get());
    symbols->addWithoutOwnership(types.fMat2x3.get());
    symbols->addWithoutOwnership(types.fMat2x4.get());
    symbols->addWithoutOwnership(types.fMat3x2.get());
    symbols->addWithoutOwnership(types.fMat3x3.get());
    symbols->addWithoutOwnership(types.fMat3x4.get());
    symbols->addWithoutOwnership(types.fMat4x2.get());
    symbols->addWithoutOwnership(types.fMat4x3.get());
    symbols->addWithoutOwnership(types.fMat4x4.get());

    // Hide all the private symbols by aliasing them all to "invalid". This will prevent code from
    // using built-in names like `sampler2D` as variable names.
    for (BuiltinTypePtr privateType : kPrivateTypes) {
        symbols->add(Type::MakeAliasType((types.*privateType)->name(), *types.fInvalid));
    }
    symbols->add(Type::MakeAliasType("sk_Caps", *types.fInvalid));
}

static void add_compute_type_aliases(SkSL::SymbolTable* symbols, const SkSL::BuiltinTypes& types) {
    // A `texture2D` in a compute shader should generally mean "read-write" texture access, not
    // "sample" texture access. Remap the name `texture2D` to point to `readWriteTexture2D`.
    symbols->add(Type::MakeAliasType("texture2D", *types.fReadWriteTexture2D));
}

const BuiltinTypes& ModuleLoader::builtinTypes() {
    return fModuleLoader.fBuiltinTypes;
}

ModifiersPool& ModuleLoader::coreModifiers() {
    return fModuleLoader.fCoreModifiers;
}

const ParsedModule& ModuleLoader::rootModule() {
    return fModuleLoader.fRootModule;
}

std::shared_ptr<SymbolTable>& ModuleLoader::rootSymbolTableWithPublicTypes() {
    if (!fModuleLoader.fRootSymbolTableWithPublicTypes) {
        fModuleLoader.fRootSymbolTableWithPublicTypes =
                std::make_shared<SymbolTable>(this->rootModule().fSymbols, /*builtin=*/true);
        add_public_type_aliases(fModuleLoader.fRootSymbolTableWithPublicTypes.get(),
                                this->builtinTypes());
    }
    return fModuleLoader.fRootSymbolTableWithPublicTypes;
}

const ParsedModule& ModuleLoader::loadPublicModule(SkSL::Compiler* compiler) {
    if (!fModuleLoader.fPublicModule.fSymbols) {
        const ParsedModule& sharedModule = this->loadSharedModule(compiler);
        fModuleLoader.fPublicModule = compiler->parseModule(ProgramKind::kGeneric,
                                                            MODULE_DATA(public),
                                                            sharedModule,
                                                            this->coreModifiers());
        add_public_type_aliases(fModuleLoader.fPublicModule.fSymbols.get(), this->builtinTypes());
    }
    return fModuleLoader.fPublicModule;
}

const ParsedModule& ModuleLoader::loadPrivateRTShaderModule(SkSL::Compiler* compiler) {
    if (!fModuleLoader.fRuntimeShaderModule.fSymbols) {
        const ParsedModule& publicModule = this->loadPublicModule(compiler);
        fModuleLoader.fRuntimeShaderModule = compiler->parseModule(ProgramKind::kRuntimeShader,
                                                                   MODULE_DATA(rt_shader),
                                                                   publicModule,
                                                                   this->coreModifiers());
    }
    return fModuleLoader.fRuntimeShaderModule;
}

const ParsedModule& ModuleLoader::loadSharedModule(SkSL::Compiler* compiler) {
    if (!fModuleLoader.fSharedModule.fSymbols) {
        const ParsedModule& rootModule = this->rootModule();
        fModuleLoader.fSharedModule = compiler->parseModule(ProgramKind::kFragment,
                                                            MODULE_DATA(shared),
                                                            rootModule,
                                                            this->coreModifiers());
    }
    return fModuleLoader.fSharedModule;
}

const ParsedModule& ModuleLoader::loadGPUModule(SkSL::Compiler* compiler) {
    if (!fModuleLoader.fGPUModule.fSymbols) {
        const ParsedModule& sharedModule = this->loadSharedModule(compiler);
        fModuleLoader.fGPUModule = compiler->parseModule(ProgramKind::kFragment,
                                                         MODULE_DATA(gpu),
                                                         sharedModule,
                                                         this->coreModifiers());
    }
    return fModuleLoader.fGPUModule;
}

const ParsedModule& ModuleLoader::loadFragmentModule(SkSL::Compiler* compiler) {
    if (!fModuleLoader.fFragmentModule.fSymbols) {
        const ParsedModule& gpuModule = this->loadGPUModule(compiler);
        fModuleLoader.fFragmentModule = compiler->parseModule(ProgramKind::kFragment,
                                                              MODULE_DATA(frag),
                                                              gpuModule,
                                                              this->coreModifiers());
    }
    return fModuleLoader.fFragmentModule;
}

const ParsedModule& ModuleLoader::loadVertexModule(SkSL::Compiler* compiler) {
    if (!fModuleLoader.fVertexModule.fSymbols) {
        const ParsedModule& gpuModule = this->loadGPUModule(compiler);
        fModuleLoader.fVertexModule = compiler->parseModule(ProgramKind::kVertex,
                                                            MODULE_DATA(vert),
                                                            gpuModule,
                                                            this->coreModifiers());
    }
    return fModuleLoader.fVertexModule;
}

const ParsedModule& ModuleLoader::loadComputeModule(SkSL::Compiler* compiler) {
    if (!fModuleLoader.fComputeModule.fSymbols) {
        const ParsedModule& gpuModule = this->loadGPUModule(compiler);
        fModuleLoader.fComputeModule = compiler->parseModule(ProgramKind::kCompute,
                                                             MODULE_DATA(compute),
                                                             gpuModule,
                                                             this->coreModifiers());
        add_compute_type_aliases(fModuleLoader.fComputeModule.fSymbols.get(), this->builtinTypes());
    }
    return fModuleLoader.fComputeModule;
}

const ParsedModule& ModuleLoader::loadGraphiteFragmentModule(SkSL::Compiler* compiler) {
#if defined(SK_GRAPHITE_ENABLED)
    if (!fModuleLoader.fGraphiteFragmentModule.fSymbols) {
        const ParsedModule& fragmentModule = this->loadFragmentModule(compiler);
        fModuleLoader.fGraphiteFragmentModule= compiler->parseModule(ProgramKind::kGraphiteFragment,
                                                                     MODULE_DATA(graphite_frag),
                                                                     fragmentModule,
                                                                     this->coreModifiers());
    }
    return fModuleLoader.fGraphiteFragmentModule;
#else
    return this->loadFragmentModule(compiler);
#endif
}

const ParsedModule& ModuleLoader::loadGraphiteVertexModule(SkSL::Compiler* compiler) {
#if defined(SK_GRAPHITE_ENABLED)
    if (!fModuleLoader.fGraphiteVertexModule.fSymbols) {
        const ParsedModule& vertexModule = this->loadVertexModule(compiler);
        fModuleLoader.fGraphiteVertexModule = compiler->parseModule(ProgramKind::kGraphiteVertex,
                                                                    MODULE_DATA(graphite_vert),
                                                                    vertexModule,
                                                                    this->coreModifiers());
    }
    return fModuleLoader.fGraphiteVertexModule;
#else
    return this->loadVertexModule(compiler);
#endif
}

void ModuleLoader::Impl::makeRootSymbolTable() {
    fRootModule.fSymbols = std::make_shared<SymbolTable>(/*builtin=*/true);

    for (BuiltinTypePtr rootType : kRootTypes) {
        fRootModule.fSymbols->addWithoutOwnership((fBuiltinTypes.*rootType).get());
    }

    for (BuiltinTypePtr privateType : kPrivateTypes) {
        fRootModule.fSymbols->addWithoutOwnership((fBuiltinTypes.*privateType).get());
    }

    // sk_Caps is "builtin", but all references to it are resolved to Settings, so we don't need to
    // treat it as builtin (ie, no need to clone it into the Program).
    fRootModule.fSymbols->add(std::make_unique<Variable>(/*pos=*/Position(),
                                                         /*modifiersPosition=*/Position(),
                                                         fCoreModifiers.add(Modifiers{}),
                                                         "sk_Caps",
                                                         fBuiltinTypes.fSkCaps.get(),
                                                         /*builtin=*/false,
                                                         Variable::Storage::kGlobal));
}

}  // namespace SkSL
