chromium/third_party/dawn/src/tint/lang/core/ir/validator.cc

// 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/core/ir/validator.h"

#include <algorithm>
#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
#include <utility>

#include "src/tint/lang/core/intrinsic/table.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_param.h"
#include "src/tint/lang/core/ir/break_if.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/control_instruction.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/disassembler.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/function.h"
#include "src/tint/lang/core/ir/function_param.h"
#include "src/tint/lang/core/ir/if.h"
#include "src/tint/lang/core/ir/instruction.h"
#include "src/tint/lang/core/ir/instruction_result.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/member_builtin_call.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/terminate_invocation.h"
#include "src/tint/lang/core/ir/unary.h"
#include "src/tint/lang/core/ir/unreachable.h"
#include "src/tint/lang/core/ir/unused.h"
#include "src/tint/lang/core/ir/user_call.h"
#include "src/tint/lang/core/ir/var.h"
#include "src/tint/lang/core/type/bool.h"
#include "src/tint/lang/core/type/i8.h"
#include "src/tint/lang/core/type/memory_view.h"
#include "src/tint/lang/core/type/pointer.h"
#include "src/tint/lang/core/type/reference.h"
#include "src/tint/lang/core/type/type.h"
#include "src/tint/lang/core/type/u8.h"
#include "src/tint/lang/core/type/vector.h"
#include "src/tint/lang/core/type/void.h"
#include "src/tint/utils/containers/hashset.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/diagnostic/diagnostic.h"
#include "src/tint/utils/ice/ice.h"
#include "src/tint/utils/macros/defer.h"
#include "src/tint/utils/result/result.h"
#include "src/tint/utils/rtti/castable.h"
#include "src/tint/utils/rtti/switch.h"
#include "src/tint/utils/text/styled_text.h"
#include "src/tint/utils/text/text_style.h"

/// If set to 1 then the Tint will dump the IR when validating.
#define TINT_DUMP_IR_WHEN_VALIDATING
#if TINT_DUMP_IR_WHEN_VALIDATING
#include <iostream>
#include "src/tint/utils/text/styled_text_printer.h"
#endif

usingnamespacetint::core::fluent_types;  // NOLINT

namespace tint::core::ir {

namespace {

/// @returns the parent block of @p block
const Block* ParentBlockOf(const Block* block) {}

/// @returns true if @p block directly or transitively holds the instruction @p inst
bool TransitivelyHolds(const Block* block, const Instruction* inst) {}

/// The core IR validator.
class Validator {};

Validator::Validator(const Module& mod, Capabilities capabilities)
    :{}

Validator::~Validator() = default;

Disassembler& Validator::Disassemble() {}

Result<SuccessType> Validator::Run() {}

void Validator::CheckForOrphanedInstructions() {}

void Validator::CheckForNonFragmentDiscards() {}

void Validator::RunStructuralSoundnessChecks() {}

diag::Diagnostic& Validator::AddError(const Instruction* inst) {}

diag::Diagnostic& Validator::AddError(const Instruction* inst, size_t idx) {}

diag::Diagnostic& Validator::AddResultError(const Instruction* inst, size_t idx) {}

diag::Diagnostic& Validator::AddError(const Block* blk) {}

diag::Diagnostic& Validator::AddError(const BlockParam* param) {}

diag::Diagnostic& Validator::AddError(const Function* func) {}

diag::Diagnostic& Validator::AddError(const FunctionParam* param) {}

diag::Diagnostic& Validator::AddNote(const Instruction* inst) {}

diag::Diagnostic& Validator::AddNote(const Function* func) {}

diag::Diagnostic& Validator::AddOperandNote(const Instruction* inst, size_t idx) {}

diag::Diagnostic& Validator::AddResultNote(const Instruction* inst, size_t idx) {}

diag::Diagnostic& Validator::AddNote(const Block* blk) {}

diag::Diagnostic& Validator::AddError(Source src) {}

diag::Diagnostic& Validator::AddNote(Source src) {}

void Validator::AddDeclarationNote(const CastableBase* decl) {}

void Validator::AddDeclarationNote(const Block* block) {}

void Validator::AddDeclarationNote(const BlockParam* param) {}

void Validator::AddDeclarationNote(const Function* fn) {}

void Validator::AddDeclarationNote(const FunctionParam* param) {}

void Validator::AddDeclarationNote(const Instruction* inst) {}

void Validator::AddDeclarationNote(const InstructionResult* res) {}

StyledText Validator::NameOf(const CastableBase* decl) {}

StyledText Validator::NameOf(const type::Type* ty) {}

StyledText Validator::NameOf(const Value* value) {}

StyledText Validator::NameOf(const Instruction* inst) {}

StyledText Validator::NameOf(const Block* block) {}

bool Validator::CheckResult(const Instruction* inst, size_t idx) {}

bool Validator::CheckResults(const ir::Instruction* inst, std::optional<size_t> count = {}

bool Validator::CheckOperand(const Instruction* inst, size_t idx) {}

bool Validator::CheckOperands(const ir::Instruction* inst,
                              size_t min_count,
                              std::optional<size_t> max_count) {}

bool Validator::CheckOperands(const ir::Instruction* inst, std::optional<size_t> count = {}

bool Validator::CheckResultsAndOperandRange(const ir::Instruction* inst,
                                            size_t num_results,
                                            size_t min_operands,
                                            std::optional<size_t> max_operands = {}

bool Validator::CheckResultsAndOperands(const ir::Instruction* inst,
                                        size_t num_results,
                                        size_t num_operands) {}

// TODO(353498500): Remove this function once it is no longer used.
void Validator::CheckOperandNotNull(const Instruction* inst, const ir::Value* operand, size_t idx) {}

void Validator::CheckType(const core::type::Type* root,
                          std::function<diag::Diagnostic&()> diag,
                          Capabilities ignore_caps) {}

void Validator::CheckRootBlock(const Block* blk) {}

void Validator::CheckFunction(const Function* func) {}

void Validator::ProcessTasks() {}

void Validator::QueueBlock(const Block* blk) {}

void Validator::BeginBlock(const Block* blk) {}

void Validator::EndBlock() {}

void Validator::QueueInstructions(const Instruction* inst) {}

void Validator::CheckInstruction(const Instruction* inst) {}

void Validator::CheckVar(const Var* var) {}

void Validator::CheckLet(const Let* let) {}

void Validator::CheckCall(const Call* call) {}

void Validator::CheckBitcast(const Bitcast* bitcast) {}

void Validator::CheckBuiltinCall(const BuiltinCall* call) {}

void Validator::CheckMemberBuiltinCall(const MemberBuiltinCall* call) {}

void Validator::CheckConstruct(const Construct* construct) {}

void Validator::CheckConvert(const Convert* convert) {}

void Validator::CheckDiscard(const tint::core::ir::Discard* discard) {}

void Validator::CheckUserCall(const UserCall* call) {}

void Validator::CheckAccess(const Access* a) {}

void Validator::CheckBinary(const Binary* b) {}

void Validator::CheckUnary(const Unary* u) {}

void Validator::CheckIf(const If* if_) {}

void Validator::CheckLoop(const Loop* l) {}

void Validator::CheckLoopBody(const Loop* loop) {}

void Validator::CheckLoopContinuing(const Loop* loop) {}

void Validator::CheckSwitch(const Switch* s) {}

void Validator::CheckSwizzle(const Swizzle* s) {}

void Validator::CheckTerminator(const Terminator* b) {}

void Validator::CheckBreakIf(const BreakIf* b) {}

void Validator::CheckContinue(const Continue* c) {}

void Validator::CheckExit(const Exit* e) {}

void Validator::CheckNextIteration(const NextIteration* n) {}

void Validator::CheckExitIf(const ExitIf* e) {}

void Validator::CheckReturn(const Return* ret) {}

void Validator::CheckControlsAllowingIf(const Exit* exit, const Instruction* control) {}

void Validator::CheckExitSwitch(const ExitSwitch* s) {}

void Validator::CheckExitLoop(const ExitLoop* l) {}

void Validator::CheckLoad(const Load* l) {}

void Validator::CheckStore(const Store* s) {}

void Validator::CheckLoadVectorElement(const LoadVectorElement* l) {}

void Validator::CheckStoreVectorElement(const StoreVectorElement* s) {}

void Validator::CheckOperandsMatchTarget(const Instruction* source_inst,
                                         size_t source_operand_offset,
                                         size_t source_operand_count,
                                         const CastableBase* target,
                                         VectorRef<const Value*> target_values) {}

const core::type::Type* Validator::GetVectorPtrElementType(const Instruction* inst, size_t idx) {}

}  // namespace

Result<SuccessType> Validate(const Module& mod, Capabilities capabilities) {}

Result<SuccessType> ValidateAndDumpIfNeeded([[maybe_unused]] const Module& ir,
                                            [[maybe_unused]] const char* msg,
                                            [[maybe_unused]] Capabilities capabilities) {}

}  // namespace tint::core::ir