1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! Reflect functions for SPIR-V instructions.

use crate::spirv;

/// Returns true if the given opcode is for a location debug instruction.
pub fn is_location_debug(opcode: spirv::Op) -> bool {
    matches!(opcode, spirv::Op::Line | spirv::Op::NoLine)
}

/// Returns true if the given opcode is for a non-location debug instruction.
pub fn is_nonlocation_debug(opcode: spirv::Op) -> bool {
    matches!(
        opcode,
        spirv::Op::SourceContinued
            | spirv::Op::Source
            | spirv::Op::SourceExtension
            | spirv::Op::Name
            | spirv::Op::MemberName
            | spirv::Op::String
    )
}

/// Returns true if the given opcode is for a debug instruction.
pub fn is_debug(opcode: spirv::Op) -> bool {
    is_location_debug(opcode) || is_nonlocation_debug(opcode)
}

/// Returns true if the given opcode is for an annotation instruction.
pub fn is_annotation(opcode: spirv::Op) -> bool {
    matches!(
        opcode,
        spirv::Op::Decorate
            | spirv::Op::MemberDecorate
            | spirv::Op::DecorationGroup
            | spirv::Op::GroupDecorate
            | spirv::Op::GroupMemberDecorate
            | spirv::Op::DecorateString
            | spirv::Op::MemberDecorateStringGOOGLE
    )
}

/// Returns true if the given opcode is for a type-declaring instruction.
pub fn is_type(opcode: spirv::Op) -> bool {
    matches!(
        opcode,
        spirv::Op::TypeVoid
            | spirv::Op::TypeBool
            | spirv::Op::TypeInt
            | spirv::Op::TypeFloat
            | spirv::Op::TypeVector
            | spirv::Op::TypeMatrix
            | spirv::Op::TypeImage
            | spirv::Op::TypeSampler
            | spirv::Op::TypeSampledImage
            | spirv::Op::TypeArray
            | spirv::Op::TypeRuntimeArray
            | spirv::Op::TypeStruct
            | spirv::Op::TypeOpaque
            | spirv::Op::TypePointer
            | spirv::Op::TypeFunction
            | spirv::Op::TypeEvent
            | spirv::Op::TypeDeviceEvent
            | spirv::Op::TypeReserveId
            | spirv::Op::TypeQueue
            | spirv::Op::TypePipe
            | spirv::Op::TypeAccelerationStructureKHR
            | spirv::Op::TypeRayQueryKHR
            | spirv::Op::TypeForwardPointer
    )
}

/// Returns true if the given opcode is for a constant-defining instruction.
pub fn is_constant(opcode: spirv::Op) -> bool {
    matches!(
        opcode,
        spirv::Op::ConstantTrue
            | spirv::Op::ConstantFalse
            | spirv::Op::Constant
            | spirv::Op::ConstantComposite
            | spirv::Op::ConstantSampler
            | spirv::Op::ConstantNull
            | spirv::Op::SpecConstantTrue
            | spirv::Op::SpecConstantFalse
            | spirv::Op::SpecConstant
            | spirv::Op::SpecConstantComposite
            | spirv::Op::SpecConstantOp
    )
}

/// Returns true if the given opcode is for a variable-defining instruction.
pub fn is_variable(opcode: spirv::Op) -> bool {
    opcode == spirv::Op::Variable
}

/// Returns true if the given opcode is a return instruction.
pub fn is_return(opcode: spirv::Op) -> bool {
    matches!(opcode, spirv::Op::Return | spirv::Op::ReturnValue)
}

/// Returns true if the given opcode aborts execution.
pub fn is_abort(opcode: spirv::Op) -> bool {
    matches!(
        opcode,
        spirv::Op::Kill
            | spirv::Op::TerminateInvocation
            | spirv::Op::TerminateRayKHR
            | spirv::Op::IgnoreIntersectionKHR
            | spirv::Op::Unreachable
    )
}

/// Returns true if the given opcode is a return instruction or it aborts
/// execution.
pub fn is_return_or_abort(opcode: spirv::Op) -> bool {
    is_return(opcode) || is_abort(opcode)
}

/// Returns true if the given opcode is a branch instruction.
pub fn is_branch(opcode: spirv::Op) -> bool {
    matches!(
        opcode,
        spirv::Op::Branch | spirv::Op::BranchConditional | spirv::Op::Switch
    )
}

/// Returns true if the given opcode is for a terminator instruction.
pub fn is_block_terminator(opcode: spirv::Op) -> bool {
    is_branch(opcode) || is_return_or_abort(opcode)
}