// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/tint/ir/builder_impl.h"

#include <iostream>

#include "src/tint/ast/alias.h"
#include "src/tint/ast/binary_expression.h"
#include "src/tint/ast/bitcast_expression.h"
#include "src/tint/ast/block_statement.h"
#include "src/tint/ast/bool_literal_expression.h"
#include "src/tint/ast/break_if_statement.h"
#include "src/tint/ast/break_statement.h"
#include "src/tint/ast/call_expression.h"
#include "src/tint/ast/call_statement.h"
#include "src/tint/ast/const_assert.h"
#include "src/tint/ast/continue_statement.h"
#include "src/tint/ast/float_literal_expression.h"
#include "src/tint/ast/for_loop_statement.h"
#include "src/tint/ast/function.h"
#include "src/tint/ast/id_attribute.h"
#include "src/tint/ast/identifier.h"
#include "src/tint/ast/identifier_expression.h"
#include "src/tint/ast/if_statement.h"
#include "src/tint/ast/int_literal_expression.h"
#include "src/tint/ast/literal_expression.h"
#include "src/tint/ast/loop_statement.h"
#include "src/tint/ast/override.h"
#include "src/tint/ast/return_statement.h"
#include "src/tint/ast/statement.h"
#include "src/tint/ast/struct.h"
#include "src/tint/ast/struct_member_align_attribute.h"
#include "src/tint/ast/struct_member_size_attribute.h"
#include "src/tint/ast/switch_statement.h"
#include "src/tint/ast/templated_identifier.h"
#include "src/tint/ast/variable_decl_statement.h"
#include "src/tint/ast/while_statement.h"
#include "src/tint/ir/function.h"
#include "src/tint/ir/if.h"
#include "src/tint/ir/loop.h"
#include "src/tint/ir/module.h"
#include "src/tint/ir/switch.h"
#include "src/tint/ir/terminator.h"
#include "src/tint/program.h"
#include "src/tint/sem/builtin.h"
#include "src/tint/sem/call.h"
#include "src/tint/sem/materialize.h"
#include "src/tint/sem/module.h"
#include "src/tint/sem/switch_statement.h"
#include "src/tint/sem/value_constructor.h"
#include "src/tint/sem/value_conversion.h"
#include "src/tint/sem/value_expression.h"
#include "src/tint/switch.h"
#include "src/tint/type/void.h"

namespace tint::ir {
namespace {

using ResultType = utils::Result<Module>;

class FlowStackScope {
  public:
    FlowStackScope(BuilderImpl* impl, FlowNode* node) : impl_(impl) {
        impl_->flow_stack.Push(node);
    }

    ~FlowStackScope() { impl_->flow_stack.Pop(); }

  private:
    BuilderImpl* impl_;
};

bool IsBranched(const Block* b) {
    return b->branch.target != nullptr;
}

bool IsConnected(const FlowNode* b) {
    // Function is always connected as it's the start.
    if (b->Is<ir::Function>()) {
        return true;
    }

    for (auto* parent : b->inbound_branches) {
        if (IsConnected(parent)) {
            return true;
        }
    }
    // Getting here means all the incoming branches are disconnected.
    return false;
}

}  // namespace

BuilderImpl::BuilderImpl(const Program* program)
    : program_(program),
      clone_ctx_{
          type::CloneContext{{&program->Symbols()}, {&builder.ir.symbols, &builder.ir.types}},
          {&builder.ir.constants}} {}

BuilderImpl::~BuilderImpl() = default;

void BuilderImpl::add_error(const Source& s, const std::string& err) {
    diagnostics_.add_error(tint::diag::System::IR, err, s);
}

void BuilderImpl::BranchTo(FlowNode* node, utils::VectorRef<Value*> args) {
    TINT_ASSERT(IR, current_flow_block);
    TINT_ASSERT(IR, !IsBranched(current_flow_block));

    builder.Branch(current_flow_block, node, args);
    current_flow_block = nullptr;
}

void BuilderImpl::BranchToIfNeeded(FlowNode* node) {
    if (!current_flow_block || IsBranched(current_flow_block)) {
        return;
    }
    BranchTo(node);
}

FlowNode* BuilderImpl::FindEnclosingControl(ControlFlags flags) {
    for (auto it = flow_stack.rbegin(); it != flow_stack.rend(); ++it) {
        if ((*it)->Is<Loop>()) {
            return *it;
        }
        if (flags == ControlFlags::kExcludeSwitch) {
            continue;
        }
        if ((*it)->Is<Switch>()) {
            return *it;
        }
    }
    return nullptr;
}

Symbol BuilderImpl::CloneSymbol(Symbol sym) const {
    return clone_ctx_.type_ctx.dst.st->Register(clone_ctx_.type_ctx.src.st->NameFor(sym));
}

ResultType BuilderImpl::Build() {
    auto* sem = program_->Sem().Module();

    for (auto* decl : sem->DependencyOrderedDeclarations()) {
        bool ok = tint::Switch(
            decl,  //
            [&](const ast::Struct*) {
                // Will be encoded into the `type::Struct` when used. We will then hoist all
                // used structs up to module scope when converting IR.
                return true;
            },
            [&](const ast::Alias*) {
                // Folded away and doesn't appear in the IR.
                return true;
            },
            // [&](const ast::Variable* var) {
            // TODO(dsinclair): Implement
            // },
            [&](const ast::Function* func) { return EmitFunction(func); },
            // [&](const ast::Enable*) {
            // TODO(dsinclair): Implement? I think these need to be passed along so further stages
            // know what is enabled.
            // },
            [&](const ast::ConstAssert*) {
                // Evaluated by the resolver, drop from the IR.
                return true;
            },
            [&](Default) {
                add_error(decl->source, "unknown type: " + std::string(decl->TypeInfo().name));
                return true;
            });
        if (!ok) {
            return utils::Failure;
        }
    }

    return ResultType{std::move(builder.ir)};
}

bool BuilderImpl::EmitFunction(const ast::Function* ast_func) {
    // The flow stack should have been emptied when the previous function finished building.
    TINT_ASSERT(IR, flow_stack.IsEmpty());

    auto* ir_func = builder.CreateFunction();
    ir_func->name = CloneSymbol(ast_func->name->symbol);
    current_function_ = ir_func;
    builder.ir.functions.Push(ir_func);

    ast_to_flow_[ast_func] = ir_func;

    if (ast_func->IsEntryPoint()) {
        builder.ir.entry_points.Push(ir_func);
    }

    {
        FlowStackScope scope(this, ir_func);

        current_flow_block = ir_func->start_target;
        if (!EmitStatements(ast_func->body->statements)) {
            return false;
        }

        // TODO(dsinclair): Store return type and attributes
        // TODO(dsinclair): Store parameters
        // TODO(dsinclair): Store attributes

        // If the branch target has already been set then a `return` was called. Only set in the
        // case where `return` wasn't called.
        BranchToIfNeeded(current_function_->end_target);
    }

    TINT_ASSERT(IR, flow_stack.IsEmpty());
    current_flow_block = nullptr;
    current_function_ = nullptr;

    return true;
}

bool BuilderImpl::EmitStatements(utils::VectorRef<const ast::Statement*> stmts) {
    for (auto* s : stmts) {
        if (!EmitStatement(s)) {
            return false;
        }

        // If the current flow block has a branch target then the rest of the statements in this
        // block are dead code. Skip them.
        if (!current_flow_block || IsBranched(current_flow_block)) {
            break;
        }
    }
    return true;
}

bool BuilderImpl::EmitStatement(const ast::Statement* stmt) {
    return tint::Switch(
        stmt,
        // [&](const ast::AssignmentStatement* a) {
        // TODO(dsinclair): Implement
        // },
        [&](const ast::BlockStatement* b) { return EmitBlock(b); },
        [&](const ast::BreakStatement* b) { return EmitBreak(b); },
        [&](const ast::BreakIfStatement* b) { return EmitBreakIf(b); },
        [&](const ast::CallStatement* c) { return EmitCall(c); },
        // [&](const ast::CompoundAssignmentStatement* c) {
        // TODO(dsinclair): Implement
        // },
        [&](const ast::ContinueStatement* c) { return EmitContinue(c); },
        // [&](const ast::DiscardStatement* d) {
        // TODO(dsinclair): Implement
        // },
        [&](const ast::IfStatement* i) { return EmitIf(i); },
        [&](const ast::LoopStatement* l) { return EmitLoop(l); },
        [&](const ast::ForLoopStatement* l) { return EmitForLoop(l); },
        [&](const ast::WhileStatement* l) { return EmitWhile(l); },
        [&](const ast::ReturnStatement* r) { return EmitReturn(r); },
        [&](const ast::SwitchStatement* s) { return EmitSwitch(s); },
        [&](const ast::VariableDeclStatement* v) { return EmitVariable(v->variable); },
        [&](const ast::ConstAssert*) {
            return true;  // Not emitted
        },
        [&](Default) {
            add_error(stmt->source,
                      "unknown statement type: " + std::string(stmt->TypeInfo().name));
            // TODO(dsinclair): This should return `false`, switch back when all
            // the cases are handled.
            return true;
        });
}

bool BuilderImpl::EmitBlock(const ast::BlockStatement* block) {
    // Note, this doesn't need to emit a Block as the current block flow node should be
    // sufficient as the blocks all get flattened. Each flow control node will inject the basic
    // blocks it requires.
    return EmitStatements(block->statements);
}

bool BuilderImpl::EmitIf(const ast::IfStatement* stmt) {
    auto* if_node = builder.CreateIf();

    // Emit the if condition into the end of the preceding block
    auto reg = EmitExpression(stmt->condition);
    if (!reg) {
        return false;
    }
    if_node->condition = reg.Get();

    BranchTo(if_node);

    ast_to_flow_[stmt] = if_node;

    {
        FlowStackScope scope(this, if_node);

        current_flow_block = if_node->true_.target->As<Block>();
        if (!EmitStatement(stmt->body)) {
            return false;
        }
        // If the true branch did not execute control flow, then go to the merge target
        BranchToIfNeeded(if_node->merge.target);

        current_flow_block = if_node->false_.target->As<Block>();
        if (stmt->else_statement && !EmitStatement(stmt->else_statement)) {
            return false;
        }
        // If the false branch did not execute control flow, then go to the merge target
        BranchToIfNeeded(if_node->merge.target);
    }
    current_flow_block = nullptr;

    // If both branches went somewhere, then they both returned, continued or broke. So,
    // there is no need for the if merge-block and there is nothing to branch to the merge
    // block anyway.
    if (IsConnected(if_node->merge.target)) {
        current_flow_block = if_node->merge.target->As<Block>();
    }

    return true;
}

bool BuilderImpl::EmitLoop(const ast::LoopStatement* stmt) {
    auto* loop_node = builder.CreateLoop();

    BranchTo(loop_node);

    ast_to_flow_[stmt] = loop_node;

    {
        FlowStackScope scope(this, loop_node);

        current_flow_block = loop_node->start.target->As<Block>();
        if (!EmitStatement(stmt->body)) {
            return false;
        }

        // The current block didn't `break`, `return` or `continue`, go to the continuing block.
        BranchToIfNeeded(loop_node->continuing.target);

        current_flow_block = loop_node->continuing.target->As<Block>();
        if (stmt->continuing) {
            if (!EmitStatement(stmt->continuing)) {
                return false;
            }
        }

        // Branch back to the start node if the continue target didn't branch out already
        BranchToIfNeeded(loop_node->start.target);
    }

    // The loop merge can get disconnected if the loop returns directly, or the continuing target
    // branches, eventually, to the merge, but nothing branched to the continuing target.
    current_flow_block = loop_node->merge.target->As<Block>();
    if (!IsConnected(loop_node->merge.target)) {
        current_flow_block = nullptr;
    }
    return true;
}

bool BuilderImpl::EmitWhile(const ast::WhileStatement* stmt) {
    auto* loop_node = builder.CreateLoop();
    // Continue is always empty, just go back to the start
    TINT_ASSERT(IR, loop_node->continuing.target->Is<Block>());
    builder.Branch(loop_node->continuing.target->As<Block>(), loop_node->start.target,
                   utils::Empty);

    BranchTo(loop_node);

    ast_to_flow_[stmt] = loop_node;

    {
        FlowStackScope scope(this, loop_node);

        current_flow_block = loop_node->start.target->As<Block>();

        // Emit the while condition into the start target of the loop
        auto reg = EmitExpression(stmt->condition);
        if (!reg) {
            return false;
        }

        // Create an `if (cond) {} else {break;}` control flow
        auto* if_node = builder.CreateIf();
        TINT_ASSERT(IR, if_node->true_.target->Is<Block>());
        builder.Branch(if_node->true_.target->As<Block>(), if_node->merge.target, utils::Empty);

        TINT_ASSERT(IR, if_node->false_.target->Is<Block>());
        builder.Branch(if_node->false_.target->As<Block>(), loop_node->merge.target, utils::Empty);
        if_node->condition = reg.Get();

        BranchTo(if_node);

        current_flow_block = if_node->merge.target->As<Block>();
        if (!EmitStatement(stmt->body)) {
            return false;
        }

        BranchToIfNeeded(loop_node->continuing.target);
    }
    // The while loop always has a path to the merge target as the break statement comes before
    // anything inside the loop.
    current_flow_block = loop_node->merge.target->As<Block>();
    return true;
}

bool BuilderImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
    auto* loop_node = builder.CreateLoop();
    TINT_ASSERT(IR, loop_node->continuing.target->Is<Block>());
    builder.Branch(loop_node->continuing.target->As<Block>(), loop_node->start.target,
                   utils::Empty);

    if (stmt->initializer) {
        // Emit the for initializer before branching to the loop
        if (!EmitStatement(stmt->initializer)) {
            return false;
        }
    }

    BranchTo(loop_node);

    ast_to_flow_[stmt] = loop_node;

    {
        FlowStackScope scope(this, loop_node);

        current_flow_block = loop_node->start.target->As<Block>();

        if (stmt->condition) {
            // Emit the condition into the target target of the loop
            auto reg = EmitExpression(stmt->condition);
            if (!reg) {
                return false;
            }

            // Create an `if (cond) {} else {break;}` control flow
            auto* if_node = builder.CreateIf();
            TINT_ASSERT(IR, if_node->true_.target->Is<Block>());
            builder.Branch(if_node->true_.target->As<Block>(), if_node->merge.target, utils::Empty);

            TINT_ASSERT(IR, if_node->false_.target->Is<Block>());
            builder.Branch(if_node->false_.target->As<Block>(), loop_node->merge.target,
                           utils::Empty);
            if_node->condition = reg.Get();

            BranchTo(if_node);
            current_flow_block = if_node->merge.target->As<Block>();
        }

        if (!EmitStatement(stmt->body)) {
            return false;
        }

        BranchToIfNeeded(loop_node->continuing.target);

        if (stmt->continuing) {
            current_flow_block = loop_node->continuing.target->As<Block>();
            if (!EmitStatement(stmt->continuing)) {
                return false;
            }
        }
    }
    // The while loop always has a path to the merge target as the break statement comes before
    // anything inside the loop.
    current_flow_block = loop_node->merge.target->As<Block>();
    return true;
}

bool BuilderImpl::EmitSwitch(const ast::SwitchStatement* stmt) {
    auto* switch_node = builder.CreateSwitch();

    // Emit the condition into the preceding block
    auto reg = EmitExpression(stmt->condition);
    if (!reg) {
        return false;
    }
    switch_node->condition = reg.Get();

    BranchTo(switch_node);

    ast_to_flow_[stmt] = switch_node;

    {
        FlowStackScope scope(this, switch_node);

        const auto* sem = program_->Sem().Get(stmt);
        for (const auto* c : sem->Cases()) {
            utils::Vector<Switch::CaseSelector, 4> selectors;
            for (const auto* selector : c->Selectors()) {
                if (selector->IsDefault()) {
                    selectors.Push({nullptr});
                } else {
                    selectors.Push({builder.Constant(selector->Value()->Clone(clone_ctx_))});
                }
            }

            current_flow_block = builder.CreateCase(switch_node, selectors);
            if (!EmitStatement(c->Body()->Declaration())) {
                return false;
            }
            BranchToIfNeeded(switch_node->merge.target);
        }
    }
    current_flow_block = nullptr;

    if (IsConnected(switch_node->merge.target)) {
        current_flow_block = switch_node->merge.target->As<Block>();
    }

    return true;
}

bool BuilderImpl::EmitReturn(const ast::ReturnStatement* stmt) {
    utils::Vector<Value*, 1> ret_value;
    if (stmt->value) {
        auto ret = EmitExpression(stmt->value);
        if (!ret) {
            return false;
        }
        ret_value.Push(ret.Get());
    }

    BranchTo(current_function_->end_target, std::move(ret_value));
    return true;
}

bool BuilderImpl::EmitBreak(const ast::BreakStatement*) {
    auto* current_control = FindEnclosingControl(ControlFlags::kNone);
    TINT_ASSERT(IR, current_control);

    if (auto* c = current_control->As<Loop>()) {
        BranchTo(c->merge.target);
    } else if (auto* s = current_control->As<Switch>()) {
        BranchTo(s->merge.target);
    } else {
        TINT_UNREACHABLE(IR, diagnostics_);
        return false;
    }

    return true;
}

bool BuilderImpl::EmitContinue(const ast::ContinueStatement*) {
    auto* current_control = FindEnclosingControl(ControlFlags::kExcludeSwitch);
    TINT_ASSERT(IR, current_control);

    if (auto* c = current_control->As<Loop>()) {
        BranchTo(c->continuing.target);
    } else {
        TINT_UNREACHABLE(IR, diagnostics_);
    }

    return true;
}

bool BuilderImpl::EmitBreakIf(const ast::BreakIfStatement* stmt) {
    auto* if_node = builder.CreateIf();

    // Emit the break-if condition into the end of the preceding block
    auto reg = EmitExpression(stmt->condition);
    if (!reg) {
        return false;
    }
    if_node->condition = reg.Get();

    BranchTo(if_node);

    ast_to_flow_[stmt] = if_node;

    auto* current_control = FindEnclosingControl(ControlFlags::kExcludeSwitch);
    TINT_ASSERT(IR, current_control);
    TINT_ASSERT(IR, current_control->Is<Loop>());

    auto* loop = current_control->As<Loop>();

    current_flow_block = if_node->true_.target->As<Block>();
    BranchTo(loop->merge.target);

    current_flow_block = if_node->false_.target->As<Block>();
    BranchTo(if_node->merge.target);

    current_flow_block = if_node->merge.target->As<Block>();

    // The `break-if` has to be the last item in the continuing block. The false branch of the
    // `break-if` will always take us back to the start of the loop.
    BranchTo(loop->start.target);

    return true;
}

utils::Result<Value*> BuilderImpl::EmitExpression(const ast::Expression* expr) {
    return tint::Switch(
        expr,
        // [&](const ast::IndexAccessorExpression* a) {
        // TODO(dsinclair): Implement
        // },
        [&](const ast::BinaryExpression* b) { return EmitBinary(b); },
        [&](const ast::BitcastExpression* b) { return EmitBitcast(b); },
        [&](const ast::CallExpression* c) { return EmitCall(c); },
        // [&](const ast::IdentifierExpression* i) {
        // TODO(dsinclair): Implement
        // },
        [&](const ast::LiteralExpression* l) { return EmitLiteral(l); },
        // [&](const ast::MemberAccessorExpression* m) {
        // TODO(dsinclair): Implement
        // },
        // [&](const ast::PhonyExpression*) {
        // TODO(dsinclair): Implement. The call may have side effects so has to be made.
        // },
        // [&](const ast::UnaryOpExpression* u) {
        // TODO(dsinclair): Implement
        // },
        [&](Default) {
            add_error(expr->source,
                      "unknown expression type: " + std::string(expr->TypeInfo().name));
            // TODO(dsinclair): This should return utils::Failure; Switch back
            // once all the above cases are handled.
            auto* v = builder.ir.types.Get<type::Void>();
            return builder.Temp(v);
        });
}

bool BuilderImpl::EmitVariable(const ast::Variable* var) {
    return tint::Switch(  //
        var,
        // [&](const ast::Var* var) {
        // TODO(dsinclair): Implement
        // },
        // [&](const ast::Let*) {
        // TODO(dsinclair): Implement
        // },
        [&](const ast::Override*) {
            add_error(var->source,
                      "found an `Override` variable. The SubstituteOverrides "
                      "transform must be run before converting to IR");
            return false;
        },
        // [&](const ast::Const* c) {
        // TODO(dsinclair): Implement
        // },
        [&](Default) {
            add_error(var->source, "unknown variable: " + std::string(var->TypeInfo().name));

            // TODO(dsinclair): This should return `false`, switch back when all
            // the cases are handled.
            return true;
        });
}

utils::Result<Value*> BuilderImpl::EmitBinary(const ast::BinaryExpression* expr) {
    auto lhs = EmitExpression(expr->lhs);
    if (!lhs) {
        return utils::Failure;
    }

    auto rhs = EmitExpression(expr->rhs);
    if (!rhs) {
        return utils::Failure;
    }

    auto* sem = program_->Sem().Get(expr);
    auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx);

    Binary* instr = nullptr;
    switch (expr->op) {
        case ast::BinaryOp::kAnd:
            instr = builder.And(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kOr:
            instr = builder.Or(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kXor:
            instr = builder.Xor(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kLogicalAnd:
            instr = builder.LogicalAnd(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kLogicalOr:
            instr = builder.LogicalOr(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kEqual:
            instr = builder.Equal(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kNotEqual:
            instr = builder.NotEqual(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kLessThan:
            instr = builder.LessThan(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kGreaterThan:
            instr = builder.GreaterThan(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kLessThanEqual:
            instr = builder.LessThanEqual(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kGreaterThanEqual:
            instr = builder.GreaterThanEqual(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kShiftLeft:
            instr = builder.ShiftLeft(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kShiftRight:
            instr = builder.ShiftRight(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kAdd:
            instr = builder.Add(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kSubtract:
            instr = builder.Subtract(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kMultiply:
            instr = builder.Multiply(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kDivide:
            instr = builder.Divide(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kModulo:
            instr = builder.Modulo(ty, lhs.Get(), rhs.Get());
            break;
        case ast::BinaryOp::kNone:
            TINT_ICE(IR, diagnostics_) << "missing binary operand type";
            return utils::Failure;
    }

    current_flow_block->instructions.Push(instr);
    return instr->Result();
}

utils::Result<Value*> BuilderImpl::EmitBitcast(const ast::BitcastExpression* expr) {
    auto val = EmitExpression(expr->expr);
    if (!val) {
        return utils::Failure;
    }

    auto* sem = program_->Sem().Get(expr);
    auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx);
    auto* instr = builder.Bitcast(ty, val.Get());

    current_flow_block->instructions.Push(instr);
    return instr->Result();
}

utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallStatement* stmt) {
    return EmitCall(stmt->expr);
}

utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallExpression* expr) {
    // If this is a materialized semantic node, just use the constant value.
    if (auto* mat = program_->Sem().Get(expr)) {
        if (mat->ConstantValue()) {
            auto* cv = mat->ConstantValue()->Clone(clone_ctx_);
            if (!cv) {
                add_error(expr->source, "failed to get constant value for call " +
                                            std::string(expr->TypeInfo().name));
                return utils::Failure;
            }
            return builder.Constant(cv);
        }
    }

    utils::Vector<Value*, 8> args;
    args.Reserve(expr->args.Length());

    // Emit the arguments
    for (const auto* arg : expr->args) {
        auto value = EmitExpression(arg);
        if (!value) {
            add_error(arg->source, "failed to convert arguments");
            return utils::Failure;
        }
        args.Push(value.Get());
    }

    auto* sem = program_->Sem().Get<sem::Call>(expr);
    if (!sem) {
        add_error(expr->source, "failed to get semantic information for call " +
                                    std::string(expr->TypeInfo().name));
        return utils::Failure;
    }

    auto* ty = sem->Target()->ReturnType()->Clone(clone_ctx_.type_ctx);

    Instruction* instr = nullptr;

    // If this is a builtin function, emit the specific builtin value
    if (auto* b = sem->Target()->As<sem::Builtin>()) {
        instr = builder.Builtin(ty, b->Type(), args);
    } else if (sem->Target()->As<sem::ValueConstructor>()) {
        instr = builder.Construct(ty, std::move(args));
    } else if (auto* conv = sem->Target()->As<sem::ValueConversion>()) {
        auto* from = conv->Source()->Clone(clone_ctx_.type_ctx);
        instr = builder.Convert(ty, from, std::move(args));
    } else if (expr->target->identifier->Is<ast::TemplatedIdentifier>()) {
        TINT_UNIMPLEMENTED(IR, diagnostics_) << "missing templated ident support";
        return utils::Failure;
    } else {
        // Not a builtin and not a templated call, so this is a user function.
        auto name = CloneSymbol(expr->target->identifier->symbol);
        instr = builder.UserCall(ty, name, std::move(args));
    }
    if (instr == nullptr) {
        return utils::Failure;
    }
    current_flow_block->instructions.Push(instr);
    return instr->Result();
}

utils::Result<Value*> BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) {
    auto* sem = program_->Sem().Get(lit);
    if (!sem) {
        add_error(lit->source, "failed to get semantic information for node " +
                                   std::string(lit->TypeInfo().name));
        return utils::Failure;
    }

    auto* cv = sem->ConstantValue()->Clone(clone_ctx_);
    if (!cv) {
        add_error(lit->source,
                  "failed to get constant value for node " + std::string(lit->TypeInfo().name));
        return utils::Failure;
    }
    return builder.Constant(cv);
}

bool BuilderImpl::EmitAttributes(utils::VectorRef<const ast::Attribute*> attrs) {
    for (auto* attr : attrs) {
        if (!EmitAttribute(attr)) {
            return false;
        }
    }
    return true;
}

bool BuilderImpl::EmitAttribute(const ast::Attribute* attr) {
    return tint::Switch(  //
        attr,
        // [&](const ast::WorkgroupAttribute* wg) {
        // TODO(dsinclair): Implement
        // },
        // [&](const ast::StageAttribute* s) {
        // TODO(dsinclair): Implement
        // },
        // [&](const ast::BindingAttribute* b) {
        // TODO(dsinclair): Implement
        // },
        // [&](const ast::GroupAttribute* g) {
        // TODO(dsinclair): Implement
        // },
        // [&](const ast::LocationAttribute* l) {
        // TODO(dsinclair): Implement
        // },
        // [&](const ast::BuiltinAttribute* b) {
        // TODO(dsinclair): Implement
        // },
        // [&](const ast::InterpolateAttribute* i) {
        // TODO(dsinclair): Implement
        // },
        // [&](const ast::InvariantAttribute* i) {
        // TODO(dsinclair): Implement
        // },
        // [&](const ast::MustUseAttribute* i) {
        // TODO(dsinclair): Implement
        // },
        [&](const ast::IdAttribute*) {
            add_error(attr->source,
                      "found an `Id` attribute. The SubstituteOverrides transform "
                      "must be run before converting to IR");
            return false;
        },
        [&](const ast::StructMemberSizeAttribute*) {
            TINT_ICE(IR, diagnostics_)
                << "StructMemberSizeAttribute encountered during IR conversion";
            return false;
        },
        [&](const ast::StructMemberAlignAttribute*) {
            TINT_ICE(IR, diagnostics_)
                << "StructMemberAlignAttribute encountered during IR conversion";
            return false;
        },
        // [&](const ast::StrideAttribute* s) {
        // TODO(dsinclair): Implement
        // },
        // [&](const ast::InternalAttribute *i) {
        // TODO(dsinclair): Implement
        // },
        [&](Default) {
            add_error(attr->source, "unknown attribute: " + std::string(attr->TypeInfo().name));
            return false;
        });
}

}  // namespace tint::ir
