// Copyright 2024 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/tint/lang/glsl/writer/raise/bitcast_polyfill.h"

#include <string>
#include <tuple>

#include "src/tint/lang/core/fluent_types.h"  // IWYU pragma: export
#include "src/tint/lang/core/ir/builder.h"
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/lang/glsl/builtin_fn.h"
#include "src/tint/lang/glsl/ir/builtin_call.h"

namespace tint::glsl::writer::raise {
namespace {

using namespace tint::core::fluent_types;     // NOLINT
using namespace tint::core::number_suffixes;  // NOLINT

/// PIMPL state for the transform.
struct State {
    /// The IR module.
    core::ir::Module& ir;

    /// The IR builder.
    core::ir::Builder b{ir};

    /// The type manager.
    core::type::Manager& ty{ir.Types()};

    // Polyfill functions for bitcast expression, BitcastType indicates the source type and the
    // destination type.
    using BitcastType =
        tint::UnorderedKeyWrapper<std::tuple<const core::type::Type*, const core::type::Type*>>;
    Hashmap<BitcastType, core::ir::Function*, 4> bitcast_funcs_{};

    /// Process the module.
    void Process() {
        Vector<core::ir::Bitcast*, 4> bitcast_worklist{};
        for (auto* inst : ir.Instructions()) {
            if (auto* bitcast = inst->As<core::ir::Bitcast>()) {
                bitcast_worklist.Push(bitcast);
                continue;
            }
        }

        for (auto* bitcast : bitcast_worklist) {
            auto* src_type = bitcast->Val()->Type();
            auto* dst_type = bitcast->Result(0)->Type();
            auto* dst_deepest = dst_type->DeepestElement();

            if (src_type == dst_type) {
                ReplaceBitcastWithValue(bitcast);
            } else if (src_type->DeepestElement()->Is<core::type::F16>()) {
                ReplaceBitcastWithFromF16Polyfill(bitcast);
            } else if (dst_deepest->Is<core::type::F16>()) {
                ReplaceBitcastWithToF16Polyfill(bitcast);
            } else if (src_type->DeepestElement()->Is<core::type::F32>()) {
                ReplaceBitcastFromF32(bitcast);
            } else if (dst_type->DeepestElement()->Is<core::type::F32>()) {
                ReplaceBitcastToF32(bitcast);
            } else {
                ReplaceBitcast(bitcast);
            }
        }
    }

    void ReplaceBitcastWithValue(core::ir::Bitcast* bitcast) {
        bitcast->Result(0)->ReplaceAllUsesWith(bitcast->Val());
        bitcast->Destroy();
    }

    core::ir::Value* CreateBitcastFromF32(const core::type::Type* type,
                                          const core::type::Type* result_type,
                                          core::ir::Value* val) {
        BuiltinFn fn = BuiltinFn::kNone;
        tint::Switch(
            type,                                                               //
            [&](const core::type::I32*) { fn = BuiltinFn::kFloatBitsToInt; },   //
            [&](const core::type::U32*) { fn = BuiltinFn::kFloatBitsToUint; },  //
            TINT_ICE_ON_NO_MATCH);

        return b.Call<glsl::ir::BuiltinCall>(result_type, fn, val)->Result(0);
    }

    void ReplaceBitcastFromF32(core::ir::Bitcast* bitcast) {
        auto* dst_type = bitcast->Result(0)->Type();
        auto* dst_deepest = dst_type->DeepestElement();

        b.InsertBefore(bitcast, [&] {
            auto* bc =
                CreateBitcastFromF32(dst_deepest, bitcast->Result(0)->Type(), bitcast->Val());
            bitcast->Result(0)->ReplaceAllUsesWith(bc);
        });
        bitcast->Destroy();
    }

    core::ir::Value* CreateBitcastToF32(const core::type::Type* src_type,
                                        const core::type::Type* dst_type,
                                        core::ir::Value* val) {
        BuiltinFn fn = BuiltinFn::kNone;
        tint::Switch(
            src_type,                                                           //
            [&](const core::type::I32*) { fn = BuiltinFn::kIntBitsToFloat; },   //
            [&](const core::type::U32*) { fn = BuiltinFn::kUintBitsToFloat; },  //
            TINT_ICE_ON_NO_MATCH);

        return b.Call<glsl::ir::BuiltinCall>(dst_type, fn, val)->Result(0);
    }

    void ReplaceBitcastToF32(core::ir::Bitcast* bitcast) {
        auto* src_type = bitcast->Val()->Type();
        auto* src_deepest = src_type->DeepestElement();

        b.InsertBefore(bitcast, [&] {
            auto* bc = CreateBitcastToF32(src_deepest, bitcast->Result(0)->Type(), bitcast->Val());
            bitcast->Result(0)->ReplaceAllUsesWith(bc);
        });
        bitcast->Destroy();
    }

    void ReplaceBitcast(core::ir::Bitcast* bitcast) {
        b.InsertBefore(bitcast,
                       [&] { b.ConvertWithResult(bitcast->DetachResult(), bitcast->Val()); });
        bitcast->Destroy();
    }

    core::ir::Function* CreateBitcastFromF16(const core::type::Type* src_type,
                                             const core::type::Type* dst_type) {
        return bitcast_funcs_.GetOrAdd(
            BitcastType{{src_type, dst_type}}, [&]() -> core::ir::Function* {
                TINT_ASSERT(src_type->Is<core::type::Vector>());

                // Generate a helper function that performs the following (in GLSL):
                //
                // ivec2 tint_bitcast_from_f16(f16vec4 src) {
                //   uvec2 r = uvec2(packFloat2x16(src.xy), packFloat2x16(src.zw));
                //   return ivec2(r);
                // }

                auto fn_name = b.ir.symbols.New("tint_bitcast_from_f16").Name();

                auto* f = b.Function(fn_name, dst_type);
                auto* src = b.FunctionParam("src", src_type);
                f->SetParams({src});

                b.Append(f->Block(), [&] {
                    auto* src_vec = src_type->As<core::type::Vector>();

                    core::ir::Value* packed = nullptr;
                    if (src_vec->Width() == 2) {
                        packed = b.Call<glsl::ir::BuiltinCall>(ty.u32(),
                                                               glsl::BuiltinFn::kPackFloat2X16, src)
                                     ->Result(0);
                    } else if (src_vec->Width() == 4) {
                        auto* left =
                            b.Call<glsl::ir::BuiltinCall>(ty.u32(), glsl::BuiltinFn::kPackFloat2X16,
                                                          b.Swizzle(ty.vec2<f16>(), src, {0, 1}));
                        auto* right =
                            b.Call<glsl::ir::BuiltinCall>(ty.u32(), glsl::BuiltinFn::kPackFloat2X16,
                                                          b.Swizzle(ty.vec2<f16>(), src, {2, 3}));
                        packed = b.Construct(ty.vec2<u32>(), left, right)->Result(0);
                    } else {
                        TINT_UNREACHABLE();
                    }

                    if (dst_type->DeepestElement()->Is<core::type::F32>()) {
                        packed =
                            CreateBitcastToF32(packed->Type()->DeepestElement(), dst_type, packed);
                    } else {
                        packed = b.Convert(dst_type, packed)->Result(0);
                    }

                    b.Return(f, packed);
                });
                return f;
            });
    }

    void ReplaceBitcastWithFromF16Polyfill(core::ir::Bitcast* bitcast) {
        auto* src_type = bitcast->Val()->Type();
        auto* dst_type = bitcast->Result(0)->Type();

        auto* f = CreateBitcastFromF16(src_type, dst_type);
        b.InsertBefore(bitcast,
                       [&] { b.CallWithResult(bitcast->DetachResult(), f, bitcast->Args()[0]); });
        bitcast->Destroy();
    }

    core::ir::Function* CreateBitcastToF16(const core::type::Type* src_type,
                                           const core::type::Type* dst_type) {
        return bitcast_funcs_.GetOrAdd(
            BitcastType{{src_type, dst_type}}, [&]() -> core::ir::Function* {
                TINT_ASSERT(dst_type->Is<core::type::Vector>());

                // Generate a helper function that performs the following (in GLSL):
                //
                // f16vec4 tint_bitcast_to_f16(ivec2 src) {
                //   uvec2 r = uvec2(src);
                //   f16vec2 v_xy = unpackFloat2x16(r.x);
                //   f16vec2 v_zw = unpackFloat2x16(r.y);
                //   return f16vec4(v_xy.x, v_xy.y, v_zw.x, v_zw.y);
                // }

                auto fn_name = b.ir.symbols.New("tint_bitcast_to_f16").Name();

                auto* f = b.Function(fn_name, dst_type);
                auto* src = b.FunctionParam("src", src_type);
                f->SetParams({src});
                b.Append(f->Block(), [&] {
                    core::ir::Value* conv = nullptr;

                    if (src->Type()->DeepestElement()->Is<core::type::F32>()) {
                        conv =
                            CreateBitcastFromF32(ty.u32(), ty.MatchWidth(ty.u32(), src_type), src);
                    } else {
                        conv = b.Convert(ty.MatchWidth(ty.u32(), src->Type()), src)->Result(0);
                    }

                    core::ir::Value* val = nullptr;
                    if (src->Type()->Is<core::type::Vector>()) {
                        auto* left = b.Call<glsl::ir::BuiltinCall>(
                            ty.vec2<f16>(), glsl::BuiltinFn::kUnpackFloat2X16,
                            b.Swizzle(ty.u32(), conv, {0}));
                        auto* right = b.Call<glsl::ir::BuiltinCall>(
                            ty.vec2<f16>(), glsl::BuiltinFn::kUnpackFloat2X16,
                            b.Swizzle(ty.u32(), conv, {1}));

                        val = b.Construct(dst_type, left, right)->Result(0);
                    } else {
                        val = b.Call<glsl::ir::BuiltinCall>(ty.vec2<f16>(),
                                                            glsl::BuiltinFn::kUnpackFloat2X16, conv)
                                  ->Result(0);
                    }
                    b.Return(f, val);
                });
                return f;
            });
    }

    void ReplaceBitcastWithToF16Polyfill(core::ir::Bitcast* bitcast) {
        auto* src_type = bitcast->Val()->Type();
        auto* dst_type = bitcast->Result(0)->Type();

        auto* f = CreateBitcastToF16(src_type, dst_type);
        b.InsertBefore(bitcast,
                       [&] { b.CallWithResult(bitcast->DetachResult(), f, bitcast->Args()[0]); });
        bitcast->Destroy();
    }
};

}  // namespace

Result<SuccessType> BitcastPolyfill(core::ir::Module& ir) {
    auto result = ValidateAndDumpIfNeeded(
        ir, "glsl.BitcastPolyfill",
        core::ir::Capabilities{core::ir::Capability::kAllowHandleVarsWithoutBindings});
    if (result != Success) {
        return result.Failure();
    }

    State{ir}.Process();

    return Success;
}

}  // namespace tint::glsl::writer::raise
