// Copyright 2023 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/wgsl/writer/ir_to_program/ir_to_program.h"

#include <string>
#include <tuple>
#include <utility>

#include "src/tint/lang/core/builtin_type.h"
#include "src/tint/lang/core/constant/splat.h"
#include "src/tint/lang/core/fluent_types.h"
#include "src/tint/lang/core/ir/access.h"
#include "src/tint/lang/core/ir/binary.h"
#include "src/tint/lang/core/ir/bitcast.h"
#include "src/tint/lang/core/ir/block.h"
#include "src/tint/lang/core/ir/break_if.h"
#include "src/tint/lang/core/ir/call.h"
#include "src/tint/lang/core/ir/constant.h"
#include "src/tint/lang/core/ir/construct.h"
#include "src/tint/lang/core/ir/continue.h"
#include "src/tint/lang/core/ir/convert.h"
#include "src/tint/lang/core/ir/core_builtin_call.h"
#include "src/tint/lang/core/ir/discard.h"
#include "src/tint/lang/core/ir/exit_if.h"
#include "src/tint/lang/core/ir/exit_loop.h"
#include "src/tint/lang/core/ir/exit_switch.h"
#include "src/tint/lang/core/ir/if.h"
#include "src/tint/lang/core/ir/instruction.h"
#include "src/tint/lang/core/ir/let.h"
#include "src/tint/lang/core/ir/load.h"
#include "src/tint/lang/core/ir/load_vector_element.h"
#include "src/tint/lang/core/ir/loop.h"
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/core/ir/multi_in_block.h"
#include "src/tint/lang/core/ir/next_iteration.h"
#include "src/tint/lang/core/ir/return.h"
#include "src/tint/lang/core/ir/store.h"
#include "src/tint/lang/core/ir/store_vector_element.h"
#include "src/tint/lang/core/ir/switch.h"
#include "src/tint/lang/core/ir/swizzle.h"
#include "src/tint/lang/core/ir/unary.h"
#include "src/tint/lang/core/ir/unreachable.h"
#include "src/tint/lang/core/ir/user_call.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/lang/core/ir/var.h"
#include "src/tint/lang/core/type/atomic.h"
#include "src/tint/lang/core/type/depth_multisampled_texture.h"
#include "src/tint/lang/core/type/depth_texture.h"
#include "src/tint/lang/core/type/multisampled_texture.h"
#include "src/tint/lang/core/type/pointer.h"
#include "src/tint/lang/core/type/reference.h"
#include "src/tint/lang/core/type/sampler.h"
#include "src/tint/lang/core/type/texture.h"
#include "src/tint/lang/wgsl/ir/builtin_call.h"
#include "src/tint/lang/wgsl/ir/unary.h"
#include "src/tint/lang/wgsl/program/program_builder.h"
#include "src/tint/lang/wgsl/resolver/resolve.h"
#include "src/tint/utils/containers/hashmap.h"
#include "src/tint/utils/containers/predicates.h"
#include "src/tint/utils/containers/reverse.h"
#include "src/tint/utils/containers/transform.h"
#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/macros/scoped_assignment.h"
#include "src/tint/utils/math/math.h"
#include "src/tint/utils/rtti/switch.h"

// Helper for incrementing nesting_depth_ and then decrementing nesting_depth_ at the end
// of the scope that holds the call.
#define SCOPED_NESTING() \
    nesting_depth_++;    \
    TINT_DEFER(nesting_depth_--)

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

namespace tint::wgsl::writer {
namespace {

class State {
  public:
    explicit State(const core::ir::Module& m) : mod(m) {}

    Program Run(const ProgramOptions& options) {
        core::ir::Capabilities caps{core::ir::Capability::kAllowRefTypes};
        if (auto res = core::ir::Validate(mod, caps); res != Success) {
            // IR module failed validation.
            b.Diagnostics() = res.Failure().reason;
            return Program{resolver::Resolve(b)};
        }

        RootBlock(mod.root_block);

        // TODO(crbug.com/tint/1902): Emit user-declared types
        for (auto& fn : mod.functions) {
            Fn(fn);
        }

        if (options.allow_non_uniform_derivatives) {
            // Suppress errors regarding non-uniform derivative operations if requested, by adding a
            // diagnostic directive to the module.
            b.DiagnosticDirective(wgsl::DiagnosticSeverity::kOff, "derivative_uniformity");
        }

        return Program{resolver::Resolve(b, options.allowed_features)};
    }

  private:
    /// The source IR module
    const core::ir::Module& mod;

    /// The target ProgramBuilder
    ProgramBuilder b;

    /// The structure for a value held by a 'let', 'var' or parameter.
    struct VariableValue {
        Symbol name;  // Name of the variable
    };

    /// The structure for an inlined value
    struct InlinedValue {
        const ast::Expression* expr = nullptr;
    };

    /// Empty struct used as a sentinel value to indicate that an ast::Value has been consumed by
    /// its single place of usage. Attempting to use this value a second time should result in an
    /// ICE.
    struct ConsumedValue {};

    using ValueBinding = std::variant<VariableValue, InlinedValue, ConsumedValue>;

    /// IR values to their representation
    Hashmap<const core::ir::Value*, ValueBinding, 32> bindings_;

    /// Names for values
    Hashmap<const core::ir::Value*, Symbol, 32> names_;

    /// The nesting depth of the currently generated AST
    /// 0  is module scope
    /// 1  is root-level function scope
    /// 2+ is within control flow
    uint32_t nesting_depth_ = 0;

    using StatementList =
        Vector<const ast::Statement*, decltype(ast::BlockStatement::statements)::static_length>;
    StatementList* statements_ = nullptr;

    /// The current switch case block
    const core::ir::Block* current_switch_case_ = nullptr;

    /// Set of enable directives emitted.
    Hashset<wgsl::Extension, 4> enables_;

    /// Map of struct to output program name.
    Hashmap<const core::type::Struct*, Symbol, 8> structs_;

    /// True if 'diagnostic(off, derivative_uniformity)' has been emitted
    bool disabled_derivative_uniformity_ = false;

    void RootBlock(const core::ir::Block* root) {
        for (auto* inst : *root) {
            tint::Switch(
                inst,                                         //
                [&](const core::ir::Var* var) { Var(var); },  //
                TINT_ICE_ON_NO_MATCH);
        }
    }
    const ast::Function* Fn(const core::ir::Function* fn) {
        SCOPED_NESTING();

        // Emit parameters.
        static constexpr size_t N = decltype(ast::Function::params)::static_length;
        auto params = tint::Transform<N>(fn->Params(), [&](const core::ir::FunctionParam* param) {
            auto ty = Type(param->Type());
            auto name = NameFor(param);
            Vector<const ast::Attribute*, 1> attrs{};
            Bind(param, name);

            // Emit parameter attributes.
            if (auto builtin = param->Builtin()) {
                switch (builtin.value()) {
                    case core::BuiltinValue::kVertexIndex:
                        attrs.Push(b.Builtin(core::BuiltinValue::kVertexIndex));
                        break;
                    case core::BuiltinValue::kInstanceIndex:
                        attrs.Push(b.Builtin(core::BuiltinValue::kInstanceIndex));
                        break;
                    case core::BuiltinValue::kPosition:
                        attrs.Push(b.Builtin(core::BuiltinValue::kPosition));
                        break;
                    case core::BuiltinValue::kFrontFacing:
                        attrs.Push(b.Builtin(core::BuiltinValue::kFrontFacing));
                        break;
                    case core::BuiltinValue::kLocalInvocationId:
                        attrs.Push(b.Builtin(core::BuiltinValue::kLocalInvocationId));
                        break;
                    case core::BuiltinValue::kLocalInvocationIndex:
                        attrs.Push(b.Builtin(core::BuiltinValue::kLocalInvocationIndex));
                        break;
                    case core::BuiltinValue::kGlobalInvocationId:
                        attrs.Push(b.Builtin(core::BuiltinValue::kGlobalInvocationId));
                        break;
                    case core::BuiltinValue::kWorkgroupId:
                        attrs.Push(b.Builtin(core::BuiltinValue::kWorkgroupId));
                        break;
                    case core::BuiltinValue::kNumWorkgroups:
                        attrs.Push(b.Builtin(core::BuiltinValue::kNumWorkgroups));
                        break;
                    case core::BuiltinValue::kSampleIndex:
                        attrs.Push(b.Builtin(core::BuiltinValue::kSampleIndex));
                        break;
                    case core::BuiltinValue::kSampleMask:
                        attrs.Push(b.Builtin(core::BuiltinValue::kSampleMask));
                        break;
                    case core::BuiltinValue::kSubgroupInvocationId:
                        Enable(wgsl::Extension::kChromiumExperimentalSubgroups);
                        attrs.Push(b.Builtin(core::BuiltinValue::kSubgroupInvocationId));
                        break;
                    case core::BuiltinValue::kSubgroupSize:
                        Enable(wgsl::Extension::kChromiumExperimentalSubgroups);
                        attrs.Push(b.Builtin(core::BuiltinValue::kSubgroupSize));
                        break;
                    default:
                        TINT_UNIMPLEMENTED() << builtin.value();
                        break;
                }
            }
            if (auto loc = param->Location()) {
                attrs.Push(b.Location(AInt(loc->value)));
                if (auto interp = loc->interpolation) {
                    attrs.Push(b.Interpolate(interp->type, interp->sampling));
                }
            }
            if (param->Invariant()) {
                attrs.Push(b.Invariant());
            }

            return b.Param(name, ty, std::move(attrs));
        });

        auto name = NameFor(fn);
        auto ret_ty = Type(fn->ReturnType());
        auto* body = Block(fn->Block());
        Vector<const ast::Attribute*, 1> attrs{};
        Vector<const ast::Attribute*, 1> ret_attrs{};

        // Emit entry point attributes.
        switch (fn->Stage()) {
            case core::ir::Function::PipelineStage::kUndefined:
                break;
            case core::ir::Function::PipelineStage::kCompute: {
                auto wgsize = fn->WorkgroupSize().value();
                attrs.Push(b.Stage(ast::PipelineStage::kCompute));
                attrs.Push(b.WorkgroupSize(AInt(wgsize[0]), AInt(wgsize[1]), AInt(wgsize[2])));
                break;
            }
            case core::ir::Function::PipelineStage::kFragment:
                attrs.Push(b.Stage(ast::PipelineStage::kFragment));
                break;
            case core::ir::Function::PipelineStage::kVertex:
                attrs.Push(b.Stage(ast::PipelineStage::kVertex));
                break;
        }

        // Emit return type attributes.
        if (auto builtin = fn->ReturnBuiltin()) {
            switch (builtin.value()) {
                case core::BuiltinValue::kPosition:
                    ret_attrs.Push(b.Builtin(core::BuiltinValue::kPosition));
                    break;
                case core::BuiltinValue::kFragDepth:
                    ret_attrs.Push(b.Builtin(core::BuiltinValue::kFragDepth));
                    break;
                case core::BuiltinValue::kSampleMask:
                    ret_attrs.Push(b.Builtin(core::BuiltinValue::kSampleMask));
                    break;
                default:
                    TINT_UNIMPLEMENTED() << builtin.value();
                    break;
            }
        }
        if (auto loc = fn->ReturnLocation()) {
            ret_attrs.Push(b.Location(AInt(loc->value)));
            if (auto interp = loc->interpolation) {
                ret_attrs.Push(b.Interpolate(interp->type, interp->sampling));
            }
        }
        if (fn->ReturnInvariant()) {
            ret_attrs.Push(b.Invariant());
        }

        return b.Func(name, std::move(params), ret_ty, body, std::move(attrs),
                      std::move(ret_attrs));
    }

    const ast::BlockStatement* Block(const core::ir::Block* block) {
        // TODO(crbug.com/tint/1902): Handle block arguments.
        return b.Block(Statements(block));
    }

    StatementList Statements(const core::ir::Block* block) {
        StatementList stmts;
        if (block) {
            TINT_SCOPED_ASSIGNMENT(statements_, &stmts);
            for (auto* inst : *block) {
                Instruction(inst);
            }
        }
        return stmts;
    }

    void Append(const ast::Statement* inst) { statements_->Push(inst); }

    void Instruction(const core::ir::Instruction* inst) {
        tint::Switch(
            inst,                                                                   //
            [&](const core::ir::Access* i) { Access(i); },                          //
            [&](const core::ir::Binary* i) { Binary(i); },                          //
            [&](const core::ir::BreakIf* i) { BreakIf(i); },                        //
            [&](const core::ir::Call* i) { Call(i); },                              //
            [&](const core::ir::Continue*) {},                                      //
            [&](const core::ir::ExitIf*) {},                                        //
            [&](const core::ir::ExitLoop* i) { ExitLoop(i); },                      //
            [&](const core::ir::ExitSwitch* i) { ExitSwitch(i); },                  //
            [&](const core::ir::If* i) { If(i); },                                  //
            [&](const core::ir::Let* i) { Let(i); },                                //
            [&](const core::ir::Load* l) { Load(l); },                              //
            [&](const core::ir::LoadVectorElement* i) { LoadVectorElement(i); },    //
            [&](const core::ir::Loop* l) { Loop(l); },                              //
            [&](const core::ir::NextIteration*) {},                                 //
            [&](const core::ir::Return* i) { Return(i); },                          //
            [&](const core::ir::Store* i) { Store(i); },                            //
            [&](const core::ir::StoreVectorElement* i) { StoreVectorElement(i); },  //
            [&](const core::ir::Switch* i) { Switch(i); },                          //
            [&](const core::ir::Swizzle* i) { Swizzle(i); },                        //
            [&](const core::ir::Unary* i) { Unary(i); },                            //
            [&](const core::ir::Unreachable*) {},                                   //
            [&](const core::ir::Var* i) { Var(i); },                                //
            TINT_ICE_ON_NO_MATCH);
    }

    void If(const core::ir::If* if_) {
        SCOPED_NESTING();

        auto true_stmts = Statements(if_->True());
        auto false_stmts = Statements(if_->False());
        if (AsShortCircuit(if_, true_stmts, false_stmts)) {
            return;
        }

        auto* cond = Expr(if_->Condition());
        auto* true_block = b.Block(std::move(true_stmts));

        switch (false_stmts.Length()) {
            case 0:
                Append(b.If(cond, true_block));
                return;
            case 1:
                if (auto* else_if = false_stmts.Front()->As<ast::IfStatement>()) {
                    Append(b.If(cond, true_block, b.Else(else_if)));
                    return;
                }
                break;
        }

        auto* false_block = b.Block(std::move(false_stmts));
        Append(b.If(cond, true_block, b.Else(false_block)));
    }

    void Loop(const core::ir::Loop* l) {
        SCOPED_NESTING();

        // Build all the initializer statements
        auto init_stmts = Statements(l->Initializer());

        // If there's a single initializer statement and meets the WGSL 'for_init' pattern, then
        // this can be used as the initializer for a for-loop.
        // @see https://www.w3.org/TR/WGSL/#syntax-for_init
        auto* init = (init_stmts.Length() == 1) &&
                             init_stmts.Front()
                                 ->IsAnyOf<ast::VariableDeclStatement, ast::AssignmentStatement,
                                           ast::CompoundAssignmentStatement,
                                           ast::IncrementDecrementStatement, ast::CallStatement>()
                         ? init_stmts.Front()
                         : nullptr;

        // Build the loop body statements. If the loop body starts with a if with the following
        // pattern, then treat it as the loop condition:
        //   if cond {
        //     block { exit_if   }
        //     block { exit_loop }
        //   }
        const ast::Expression* cond = nullptr;
        StatementList body_stmts;
        {
            TINT_SCOPED_ASSIGNMENT(statements_, &body_stmts);
            for (auto* inst : *l->Body()) {
                if (body_stmts.IsEmpty()) {
                    if (auto* if_ = inst->As<core::ir::If>()) {
                        if (if_->Results().IsEmpty() &&                          //
                            if_->True()->Length() == 1 &&                        //
                            if_->False()->Length() == 1 &&                       //
                            tint::Is<core::ir::ExitIf>(if_->True()->Front()) &&  //
                            tint::Is<core::ir::ExitLoop>(if_->False()->Front())) {
                            // Matched the loop condition.
                            cond = Expr(if_->Condition());
                            continue;  // Don't emit this as an instruction in the body.
                        }
                    }
                }

                // Process the loop body instruction. Append to 'body_stmts'
                Instruction(inst);
            }
        }

        // Build any continuing statements
        auto cont_stmts = Statements(l->Continuing());
        // If there's a single continuing statement and meets the WGSL 'for_update' pattern then
        // this can be used as the continuing for a for-loop.
        // @see https://www.w3.org/TR/WGSL/#syntax-for_update
        auto* cont =
            (cont_stmts.Length() == 1) &&
                    cont_stmts.Front()
                        ->IsAnyOf<ast::AssignmentStatement, ast::CompoundAssignmentStatement,
                                  ast::IncrementDecrementStatement, ast::CallStatement>()
                ? cont_stmts.Front()
                : nullptr;

        // Depending on 'init', 'cond' and 'cont', build a 'for', 'while' or 'loop'
        const ast::Statement* loop = nullptr;
        if ((!cont && !cont_stmts.IsEmpty())  // Non-trivial continuing
            || !cond                          // or non-trivial or no condition
        ) {
            // Build a loop
            if (cond) {
                body_stmts.Insert(0, b.If(b.Not(cond), b.Block(b.Break())));
            }
            auto* body = b.Block(std::move(body_stmts));
            loop = cont_stmts.IsEmpty() ? b.Loop(body)  //
                                        : b.Loop(body, b.Block(std::move(cont_stmts)));
            if (!init_stmts.IsEmpty()) {
                init_stmts.Push(loop);
                loop = b.Block(std::move(init_stmts));
            }
        } else if (init || cont) {
            // Build a for-loop
            auto* body = b.Block(std::move(body_stmts));
            loop = b.For(init, cond, cont, body);
            if (!init && !init_stmts.IsEmpty()) {
                init_stmts.Push(loop);
                loop = b.Block(std::move(init_stmts));
            }
        } else {
            // Build a while-loop
            auto* body = b.Block(std::move(body_stmts));
            loop = b.While(cond, body);
            if (!init_stmts.IsEmpty()) {
                init_stmts.Push(loop);
                loop = b.Block(std::move(init_stmts));
            }
        }
        statements_->Push(loop);
    }

    void Switch(const core::ir::Switch* s) {
        SCOPED_NESTING();

        auto* cond = Expr(s->Condition());

        auto cases = tint::Transform<4>(
            s->Cases(),  //
            [&](const core::ir::Switch::Case& c) -> const tint::ast::CaseStatement* {
                SCOPED_NESTING();

                const ast::BlockStatement* body = nullptr;
                {
                    TINT_SCOPED_ASSIGNMENT(current_switch_case_, c.block);
                    body = Block(c.block);
                }

                auto selectors = tint::Transform(c.selectors,  //
                                                 [&](const core::ir::Switch::CaseSelector& cs) {
                                                     return cs.IsDefault()
                                                                ? b.DefaultCaseSelector()
                                                                : b.CaseSelector(Expr(cs.val));
                                                 });
                return b.Case(std::move(selectors), body);
            });

        Append(b.Switch(cond, std::move(cases)));
    }

    void ExitSwitch(const core::ir::ExitSwitch* e) {
        if (current_switch_case_ && current_switch_case_->Terminator() == e) {
            return;  // No need to emit
        }
        Append(b.Break());
    }

    void ExitLoop(const core::ir::ExitLoop*) { Append(b.Break()); }

    void BreakIf(const core::ir::BreakIf* i) { Append(b.BreakIf(Expr(i->Condition()))); }

    void Return(const core::ir::Return* ret) {
        if (ret->Args().IsEmpty()) {
            // Return has no arguments.
            // If this block is nested withing some control flow, then we must
            // emit a 'return' statement, otherwise we've just naturally reached
            // the end of the function where the 'return' is redundant.
            if (nesting_depth_ > 1) {
                Append(b.Return());
            }
            return;
        }

        // Return has arguments - this is the return value.
        if (ret->Args().Length() != 1) {
            TINT_ICE() << "expected 1 value for return, got " << ret->Args().Length();
            return;
        }

        Append(b.Return(Expr(ret->Args().Front())));
    }

    void Var(const core::ir::Var* var) {
        auto* val = var->Result(0);
        auto* ref = As<core::type::Reference>(val->Type());
        TINT_ASSERT(ref /* converted by PtrToRef */);
        auto ty = Type(ref->StoreType());
        Symbol name = NameFor(var->Result(0));
        Bind(var->Result(0), name);

        Vector<const ast::Attribute*, 4> attrs;
        if (auto bp = var->BindingPoint()) {
            attrs.Push(b.Group(AInt(bp->group)));
            attrs.Push(b.Binding(AInt(bp->binding)));
        }

        const ast::Expression* init = nullptr;
        if (var->Initializer()) {
            init = Expr(var->Initializer());
        }
        switch (ref->AddressSpace()) {
            case core::AddressSpace::kFunction:
                Append(b.Decl(b.Var(name, ty, init, std::move(attrs))));
                return;
            case core::AddressSpace::kStorage:
                b.GlobalVar(name, ty, init, ref->Access(), ref->AddressSpace(), std::move(attrs));
                return;
            case core::AddressSpace::kHandle:
                b.GlobalVar(name, ty, init, std::move(attrs));
                return;
            default:
                b.GlobalVar(name, ty, init, ref->AddressSpace(), std::move(attrs));
                return;
        }
    }

    void Let(const core::ir::Let* let) {
        auto* result = let->Result(0);
        if (mod.NameOf(result).IsValid() || result->NumUsages() > 0) {
            Symbol name = NameFor(result);
            Append(b.Decl(b.Let(name, Expr(let->Value()))));
            Bind(result, name);
        } else {
            Append(b.Assign(b.Phony(), Expr(let->Value())));
        }
    }

    void Store(const core::ir::Store* store) {
        auto* dst = Expr(store->To());
        auto* src = Expr(store->From());
        Append(b.Assign(dst, src));
    }

    void StoreVectorElement(const core::ir::StoreVectorElement* store) {
        auto* ptr = Expr(store->To());
        auto* val = Expr(store->Value());
        Append(b.Assign(VectorMemberAccess(ptr, store->Index()), val));
    }

    void Call(const core::ir::Call* call) {
        auto args = tint::Transform<4>(call->Args(), [&](const core::ir::Value* arg) {
            // Pointer-like arguments are passed by pointer, never reference.
            return Expr(arg);
        });
        tint::Switch(
            call,  //
            [&](const core::ir::UserCall* c) {
                auto* expr = b.Call(NameFor(c->Target()), std::move(args));
                if (call->Results().IsEmpty() || !call->Result(0)->IsUsed()) {
                    Append(b.CallStmt(expr));
                    return;
                }
                Bind(c->Result(0), expr);
            },
            [&](const wgsl::ir::BuiltinCall* c) {
                if (!disabled_derivative_uniformity_ && RequiresDerivativeUniformity(c->Func())) {
                    // TODO(crbug.com/tint/1985): Be smarter about disabling derivative uniformity.
                    b.DiagnosticDirective(wgsl::DiagnosticSeverity::kOff,
                                          wgsl::CoreDiagnosticRule::kDerivativeUniformity);
                    disabled_derivative_uniformity_ = true;
                }

                switch (c->Func()) {
                    case wgsl::BuiltinFn::kSubgroupBallot:
                    case wgsl::BuiltinFn::kSubgroupBroadcast:
                        Enable(wgsl::Extension::kChromiumExperimentalSubgroups);
                        break;
                    default:
                        break;
                }

                auto* expr = b.Call(c->Func(), std::move(args));
                if (call->Results().IsEmpty() || !call->Result(0)->IsUsed()) {
                    Append(b.CallStmt(expr));
                    return;
                }
                Bind(c->Result(0), expr);
            },
            [&](const core::ir::Construct* c) {
                auto ty = Type(c->Result(0)->Type());
                Bind(c->Result(0), b.Call(ty, std::move(args)));
            },
            [&](const core::ir::Convert* c) {
                auto ty = Type(c->Result(0)->Type());
                Bind(c->Result(0), b.Call(ty, std::move(args)));
            },
            [&](const core::ir::Bitcast* c) {
                auto ty = Type(c->Result(0)->Type());
                Bind(c->Result(0), b.Bitcast(ty, args[0]));
            },
            [&](const core::ir::Discard*) { Append(b.Discard()); },  //
            TINT_ICE_ON_NO_MATCH);
    }

    void Load(const core::ir::Load* l) { Bind(l->Result(0), Expr(l->From())); }

    void LoadVectorElement(const core::ir::LoadVectorElement* l) {
        auto* vec = Expr(l->From());
        Bind(l->Result(0), VectorMemberAccess(vec, l->Index()));
    }

    void Unary(const core::ir::Unary* u) {
        const ast::Expression* expr = nullptr;
        switch (u->Op()) {
            case core::UnaryOp::kComplement:
                expr = b.Complement(Expr(u->Val()));
                break;
            case core::UnaryOp::kNegation:
                expr = b.Negation(Expr(u->Val()));
                break;
            case core::UnaryOp::kAddressOf:
                expr = b.AddressOf(Expr(u->Val()));
                break;
            case core::UnaryOp::kIndirection:
                expr = b.Deref(Expr(u->Val()));
                break;
            default:
                TINT_UNIMPLEMENTED() << u->Op();
                break;
        }
        Bind(u->Result(0), expr);
    }

    void Access(const core::ir::Access* a) {
        auto* expr = Expr(a->Object());
        auto* obj_ty = a->Object()->Type()->UnwrapRef();
        for (auto* index : a->Indices()) {
            tint::Switch(
                obj_ty,
                [&](const core::type::Vector* vec) {
                    TINT_DEFER(obj_ty = vec->type());
                    expr = VectorMemberAccess(expr, index);
                },
                [&](const core::type::Matrix* mat) {
                    obj_ty = mat->ColumnType();
                    expr = b.IndexAccessor(expr, Expr(index));
                },
                [&](const core::type::Array* arr) {
                    obj_ty = arr->ElemType();
                    expr = b.IndexAccessor(expr, Expr(index));
                },
                [&](const core::type::Struct* s) {
                    if (auto* c = index->As<core::ir::Constant>()) {
                        auto i = c->Value()->ValueAs<uint32_t>();
                        TINT_ASSERT_OR_RETURN(i < s->Members().Length());
                        auto* member = s->Members()[i];
                        obj_ty = member->Type();
                        expr = b.MemberAccessor(expr, member->Name().NameView());
                    } else {
                        TINT_ICE() << "invalid index for struct type: " << index->TypeInfo().name;
                    }
                },  //
                TINT_ICE_ON_NO_MATCH);
        }
        Bind(a->Result(0), expr);
    }

    void Swizzle(const core::ir::Swizzle* s) {
        auto* vec = Expr(s->Object());
        Vector<char, 4> components;
        for (uint32_t i : s->Indices()) {
            if (TINT_UNLIKELY(i >= 4)) {
                TINT_ICE() << "invalid swizzle index: " << i;
                return;
            }
            components.Push("xyzw"[i]);
        }
        auto* swizzle =
            b.MemberAccessor(vec, std::string_view(components.begin(), components.Length()));
        Bind(s->Result(0), swizzle);
    }

    void Binary(const core::ir::Binary* e) {
        if (e->Op() == core::BinaryOp::kEqual) {
            auto* rhs = e->RHS()->As<core::ir::Constant>();
            if (rhs && rhs->Type()->Is<core::type::Bool>() &&
                rhs->Value()->ValueAs<bool>() == false) {
                // expr == false
                Bind(e->Result(0), b.Not(Expr(e->LHS())));
                return;
            }
        }
        auto* lhs = Expr(e->LHS());
        auto* rhs = Expr(e->RHS());
        const ast::Expression* expr = nullptr;
        switch (e->Op()) {
            case core::BinaryOp::kAdd:
                expr = b.Add(lhs, rhs);
                break;
            case core::BinaryOp::kSubtract:
                expr = b.Sub(lhs, rhs);
                break;
            case core::BinaryOp::kMultiply:
                expr = b.Mul(lhs, rhs);
                break;
            case core::BinaryOp::kDivide:
                expr = b.Div(lhs, rhs);
                break;
            case core::BinaryOp::kModulo:
                expr = b.Mod(lhs, rhs);
                break;
            case core::BinaryOp::kAnd:
                expr = b.And(lhs, rhs);
                break;
            case core::BinaryOp::kOr:
                expr = b.Or(lhs, rhs);
                break;
            case core::BinaryOp::kXor:
                expr = b.Xor(lhs, rhs);
                break;
            case core::BinaryOp::kEqual:
                expr = b.Equal(lhs, rhs);
                break;
            case core::BinaryOp::kNotEqual:
                expr = b.NotEqual(lhs, rhs);
                break;
            case core::BinaryOp::kLessThan:
                expr = b.LessThan(lhs, rhs);
                break;
            case core::BinaryOp::kGreaterThan:
                expr = b.GreaterThan(lhs, rhs);
                break;
            case core::BinaryOp::kLessThanEqual:
                expr = b.LessThanEqual(lhs, rhs);
                break;
            case core::BinaryOp::kGreaterThanEqual:
                expr = b.GreaterThanEqual(lhs, rhs);
                break;
            case core::BinaryOp::kShiftLeft:
                expr = b.Shl(lhs, rhs);
                break;
            case core::BinaryOp::kShiftRight:
                expr = b.Shr(lhs, rhs);
                break;
            case core::BinaryOp::kLogicalAnd:
                expr = b.LogicalAnd(lhs, rhs);
                break;
            case core::BinaryOp::kLogicalOr:
                expr = b.LogicalOr(lhs, rhs);
                break;
        }
        Bind(e->Result(0), expr);
    }

    TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE);

    const ast::Expression* Expr(const core::ir::Value* value) {
        auto expr = tint::Switch(
            value,  //
            [&](const core::ir::Constant* c) { return Constant(c); },
            [&](Default) -> const ast::Expression* {
                auto lookup = bindings_.Get(value);
                if (TINT_UNLIKELY(!lookup)) {
                    TINT_ICE() << "Expr(" << (value ? value->TypeInfo().name : "null")
                               << ") value has no expression";
                    return nullptr;
                }
                return std::visit(
                    [&](auto&& got) -> const ast::Expression* {
                        using T = std::decay_t<decltype(got)>;

                        if constexpr (std::is_same_v<T, VariableValue>) {
                            return b.Expr(got.name);
                        }

                        if constexpr (std::is_same_v<T, InlinedValue>) {
                            auto result = got.expr;
                            // Single use (inlined) expression.
                            // Mark the bindings_ map entry as consumed.
                            *lookup = ConsumedValue{};
                            return result;
                        }

                        if constexpr (std::is_same_v<T, ConsumedValue>) {
                            TINT_ICE() << "Expr(" << value->TypeInfo().name
                                       << ") called twice on the same value";
                        } else {
                            TINT_ICE()
                                << "Expr(" << value->TypeInfo().name << ") has unhandled value";
                        }
                        return nullptr;
                    },
                    *lookup);
            });

        if (!expr) {
            return b.Expr("<error>");
        }

        return expr;
    }

    TINT_END_DISABLE_WARNING(UNREACHABLE_CODE);

    const ast::Expression* Constant(const core::ir::Constant* c) { return Constant(c->Value()); }

    const ast::Expression* Constant(const core::constant::Value* c) {
        auto composite = [&](bool can_splat) {
            auto ty = Type(c->Type());
            if (c->AllZero()) {
                return b.Call(ty);
            }
            if (can_splat && c->Is<core::constant::Splat>()) {
                return b.Call(ty, Constant(c->Index(0)));
            }

            Vector<const ast::Expression*, 8> els;
            for (size_t i = 0, n = c->NumElements(); i < n; i++) {
                els.Push(Constant(c->Index(i)));
            }
            return b.Call(ty, std::move(els));
        };
        return tint::Switch(
            c->Type(),  //
            [&](const core::type::I32*) { return b.Expr(c->ValueAs<i32>()); },
            [&](const core::type::U32*) { return b.Expr(c->ValueAs<u32>()); },
            [&](const core::type::F32*) { return b.Expr(c->ValueAs<f32>()); },
            [&](const core::type::F16*) {
                Enable(wgsl::Extension::kF16);
                return b.Expr(c->ValueAs<f16>());
            },
            [&](const core::type::Bool*) { return b.Expr(c->ValueAs<bool>()); },
            [&](const core::type::Array*) { return composite(/* can_splat */ false); },
            [&](const core::type::Vector*) { return composite(/* can_splat */ true); },
            [&](const core::type::Matrix*) { return composite(/* can_splat */ false); },
            [&](const core::type::Struct*) { return composite(/* can_splat */ false); },  //
            TINT_ICE_ON_NO_MATCH);
    }

    void Enable(wgsl::Extension ext) {
        if (enables_.Add(ext)) {
            b.Enable(ext);
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // Types
    //
    // The the case of an error:
    // * The types generating methods must return a non-null ast type, which may not be semantically
    //   legal, but is enough to populate the AST.
    // * A diagnostic error must be added to the ast::ProgramBuilder.
    // This prevents littering the ToProgram logic with expensive error checking code.
    ////////////////////////////////////////////////////////////////////////////////////////////////

    /// @param ty the type::Type
    /// @return an ast::Type from @p ty.
    /// @note May be a semantically-invalid placeholder type on error.
    ast::Type Type(const core::type::Type* ty) {
        return tint::Switch(
            ty,                                                    //
            [&](const core::type::Void*) { return ast::Type{}; },  //
            [&](const core::type::I32*) { return b.ty.i32(); },    //
            [&](const core::type::U32*) { return b.ty.u32(); },    //
            [&](const core::type::F16*) {
                Enable(wgsl::Extension::kF16);
                return b.ty.f16();
            },
            [&](const core::type::F32*) { return b.ty.f32(); },  //
            [&](const core::type::Bool*) { return b.ty.bool_(); },
            [&](const core::type::Matrix* m) {
                return b.ty.mat(Type(m->type()), m->columns(), m->rows());
            },
            [&](const core::type::Vector* v) {
                auto el = Type(v->type());
                if (v->Packed()) {
                    TINT_ASSERT(v->Width() == 3u);
                    return b.ty(core::BuiltinType::kPackedVec3, el);
                } else {
                    return b.ty.vec(el, v->Width());
                }
            },
            [&](const core::type::Array* a) {
                auto el = Type(a->ElemType());
                Vector<const ast::Attribute*, 1> attrs;
                if (!a->IsStrideImplicit()) {
                    attrs.Push(b.Stride(a->Stride()));
                }
                if (a->Count()->Is<core::type::RuntimeArrayCount>()) {
                    return b.ty.array(el, std::move(attrs));
                }
                auto count = a->ConstantCount();
                if (TINT_UNLIKELY(!count)) {
                    TINT_ICE() << core::type::Array::kErrExpectedConstantCount;
                    return b.ty.array(el, u32(1), std::move(attrs));
                }
                return b.ty.array(el, u32(count.value()), std::move(attrs));
            },
            [&](const core::type::Struct* s) { return Struct(s); },
            [&](const core::type::Atomic* a) { return b.ty.atomic(Type(a->Type())); },
            [&](const core::type::DepthTexture* t) { return b.ty.depth_texture(t->dim()); },
            [&](const core::type::DepthMultisampledTexture* t) {
                return b.ty.depth_multisampled_texture(t->dim());
            },
            [&](const core::type::ExternalTexture*) { return b.ty.external_texture(); },
            [&](const core::type::MultisampledTexture* t) {
                auto el = Type(t->type());
                return b.ty.multisampled_texture(t->dim(), el);
            },
            [&](const core::type::SampledTexture* t) {
                auto el = Type(t->type());
                return b.ty.sampled_texture(t->dim(), el);
            },
            [&](const core::type::StorageTexture* t) {
                return b.ty.storage_texture(t->dim(), t->texel_format(), t->access());
            },
            [&](const core::type::Sampler* s) { return b.ty.sampler(s->kind()); },
            [&](const core::type::Pointer* p) {
                // Note: type::Pointer always has an inferred access, but WGSL only allows an
                // explicit access in the 'storage' address space.
                auto el = Type(p->StoreType());
                auto address_space = p->AddressSpace();
                auto access = address_space == core::AddressSpace::kStorage
                                  ? p->Access()
                                  : core::Access::kUndefined;
                return b.ty.ptr(address_space, el, access);
            },
            [&](const core::type::Reference*) {
                TINT_ICE() << "reference types should never appear in the IR";
                return b.ty.i32();
            },  //
            TINT_ICE_ON_NO_MATCH);
    }

    ast::Type Struct(const core::type::Struct* s) {
        auto n = structs_.GetOrAdd(s, [&] {
            auto members = tint::Transform<8>(s->Members(), [&](const core::type::StructMember* m) {
                auto ty = Type(m->Type());
                const auto& ir_attrs = m->Attributes();
                Vector<const ast::Attribute*, 4> ast_attrs;
                if (m->Type()->Align() != m->Align()) {
                    ast_attrs.Push(b.MemberAlign(u32(m->Align())));
                }
                if (m->Type()->Size() != m->Size()) {
                    ast_attrs.Push(b.MemberSize(u32(m->Size())));
                }
                if (auto location = ir_attrs.location) {
                    ast_attrs.Push(b.Location(u32(*location)));
                }
                if (auto blend_src = ir_attrs.blend_src) {
                    Enable(wgsl::Extension::kChromiumInternalDualSourceBlending);
                    ast_attrs.Push(b.BlendSrc(u32(*blend_src)));
                }
                if (auto builtin = ir_attrs.builtin) {
                    if (RequiresSubgroups(*builtin)) {
                        Enable(wgsl::Extension::kChromiumExperimentalSubgroups);
                    }
                    ast_attrs.Push(b.Builtin(*builtin));
                }
                if (auto interpolation = ir_attrs.interpolation) {
                    ast_attrs.Push(b.Interpolate(interpolation->type, interpolation->sampling));
                }
                if (ir_attrs.invariant) {
                    ast_attrs.Push(b.Invariant());
                }
                return b.Member(m->Name().NameView(), ty, std::move(ast_attrs));
            });

            // TODO(crbug.com/tint/1902): Emit structure attributes
            Vector<const ast::Attribute*, 2> attrs;

            auto name = b.Symbols().Register(s->Name().NameView());
            b.Structure(name, std::move(members), std::move(attrs));
            return name;
        });

        return b.ty(n);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // Bindings
    ////////////////////////////////////////////////////////////////////////////////////////////////

    /// @returns the AST name for the given value, creating and returning a new name on the first
    /// call.
    Symbol NameFor(const core::ir::Value* value, std::string_view suggested = {}) {
        return names_.GetOrAdd(value, [&] {
            if (!suggested.empty()) {
                return b.Symbols().Register(suggested);
            }
            if (auto sym = mod.NameOf(value)) {
                return b.Symbols().Register(sym.NameView());
            }
            return b.Symbols().New("v");
        });
    }

    /// Associates the IR value @p value with the AST expression @p expr.
    void Bind(const core::ir::Value* value, const ast::Expression* expr) {
        TINT_ASSERT(value);
        // Value will be inlined at its place of usage.
        if (TINT_UNLIKELY(!bindings_.Add(value, InlinedValue{expr}))) {
            TINT_ICE() << "Bind(" << value->TypeInfo().name << ") called twice for same value";
        }
    }

    /// Associates the IR value @p value with the AST 'var', 'let' or parameter with the name @p
    /// name.
    void Bind(const core::ir::Value* value, Symbol name) {
        TINT_ASSERT(value);

        bool added = bindings_.Add(value, VariableValue{name});
        if (TINT_UNLIKELY(!added)) {
            TINT_ICE() << "Bind(" << value->TypeInfo().name << ") called twice for same value";
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // Helpers
    ////////////////////////////////////////////////////////////////////////////////////////////////
    bool AsShortCircuit(const core::ir::If* i,
                        const StatementList& true_stmts,
                        const StatementList& false_stmts) {
        if (i->Results().IsEmpty()) {
            return false;
        }
        auto* result = i->Result(0);
        if (!result->Type()->Is<core::type::Bool>()) {
            return false;  // Wrong result type
        }
        if (i->Exits().Count() != 2) {
            return false;  // Doesn't have two exits
        }
        if (!true_stmts.IsEmpty() || !false_stmts.IsEmpty()) {
            return false;  // True or False blocks contain statements
        }

        auto* cond = i->Condition();
        auto* true_val = i->True()->Back()->Operands().Front();
        auto* false_val = i->False()->Back()->Operands().Front();
        if (IsConstant(false_val, false)) {
            //  %res = if %cond {
            //     block {  # true
            //       exit_if %true_val;
            //     }
            //     block {  # false
            //       exit_if false;
            //     }
            //  }
            //
            // transform into:
            //
            //   res = cond && true_val;
            //
            auto* lhs = Expr(cond);
            auto* rhs = Expr(true_val);
            Bind(result, b.LogicalAnd(lhs, rhs));
            return true;
        }
        if (IsConstant(true_val, true)) {
            //  %res = if %cond {
            //     block {  # true
            //       exit_if true;
            //     }
            //     block {  # false
            //       exit_if %false_val;
            //     }
            //  }
            //
            // transform into:
            //
            //   res = cond || false_val;
            //
            auto* lhs = Expr(cond);
            auto* rhs = Expr(false_val);
            Bind(result, b.LogicalOr(lhs, rhs));
            return true;
        }
        return false;
    }

    bool IsConstant(const core::ir::Value* val, bool value) {
        if (auto* c = val->As<core::ir::Constant>()) {
            if (c->Type()->Is<core::type::Bool>()) {
                return c->Value()->ValueAs<bool>() == value;
            }
        }
        return false;
    }

    const ast::Expression* VectorMemberAccess(const ast::Expression* expr,
                                              const core::ir::Value* index) {
        if (auto* c = index->As<core::ir::Constant>()) {
            switch (c->Value()->ValueAs<int>()) {
                case 0:
                    return b.MemberAccessor(expr, "x");
                case 1:
                    return b.MemberAccessor(expr, "y");
                case 2:
                    return b.MemberAccessor(expr, "z");
                case 3:
                    return b.MemberAccessor(expr, "w");
            }
        }
        return b.IndexAccessor(expr, Expr(index));
    }

    bool RequiresDerivativeUniformity(wgsl::BuiltinFn fn) {
        switch (fn) {
            case wgsl::BuiltinFn::kDpdxCoarse:
            case wgsl::BuiltinFn::kDpdyCoarse:
            case wgsl::BuiltinFn::kFwidthCoarse:
            case wgsl::BuiltinFn::kDpdxFine:
            case wgsl::BuiltinFn::kDpdyFine:
            case wgsl::BuiltinFn::kFwidthFine:
            case wgsl::BuiltinFn::kDpdx:
            case wgsl::BuiltinFn::kDpdy:
            case wgsl::BuiltinFn::kFwidth:
            case wgsl::BuiltinFn::kTextureSample:
            case wgsl::BuiltinFn::kTextureSampleBias:
            case wgsl::BuiltinFn::kTextureSampleCompare:
                return true;
            default:
                return false;
        }
    }

    /// @returns true if the builtin value requires the kChromiumExperimentalSubgroups extension to
    /// be enabled.
    bool RequiresSubgroups(core::BuiltinValue builtin) {
        switch (builtin) {
            case core::BuiltinValue::kSubgroupInvocationId:
            case core::BuiltinValue::kSubgroupSize:
                return true;
            default:
                return false;
        }
    }
};

}  // namespace

Program IRToProgram(const core::ir::Module& i, const ProgramOptions& options) {
    return State{i}.Run(options);
}

}  // namespace tint::wgsl::writer
