Austin Eng | cc2516a | 2023-10-17 20:57:54 +0000 | [diff] [blame] | 1 | // Copyright 2022 The Dawn & Tint Authors |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 2 | // |
Austin Eng | cc2516a | 2023-10-17 20:57:54 +0000 | [diff] [blame] | 3 | // Redistribution and use in source and binary forms, with or without |
| 4 | // modification, are permitted provided that the following conditions are met: |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 5 | // |
Austin Eng | cc2516a | 2023-10-17 20:57:54 +0000 | [diff] [blame] | 6 | // 1. Redistributions of source code must retain the above copyright notice, this |
| 7 | // list of conditions and the following disclaimer. |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 8 | // |
Austin Eng | cc2516a | 2023-10-17 20:57:54 +0000 | [diff] [blame] | 9 | // 2. Redistributions in binary form must reproduce the above copyright notice, |
| 10 | // this list of conditions and the following disclaimer in the documentation |
| 11 | // and/or other materials provided with the distribution. |
| 12 | // |
| 13 | // 3. Neither the name of the copyright holder nor the names of its |
| 14 | // contributors may be used to endorse or promote products derived from |
| 15 | // this software without specific prior written permission. |
| 16 | // |
| 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
| 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 27 | |
dan sinclair | 97c3727 | 2023-07-24 17:11:53 +0000 | [diff] [blame] | 28 | #ifndef SRC_TINT_LANG_CORE_IR_BUILDER_H_ |
| 29 | #define SRC_TINT_LANG_CORE_IR_BUILDER_H_ |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 30 | |
dan sinclair | 19ebcb2 | 2022-12-15 19:17:22 +0000 | [diff] [blame] | 31 | #include <utility> |
| 32 | |
dan sinclair | 352f8c8 | 2023-07-21 00:40:07 +0000 | [diff] [blame] | 33 | #include "src/tint/lang/core/constant/composite.h" |
| 34 | #include "src/tint/lang/core/constant/scalar.h" |
| 35 | #include "src/tint/lang/core/constant/splat.h" |
dan sinclair | 97c3727 | 2023-07-24 17:11:53 +0000 | [diff] [blame] | 36 | #include "src/tint/lang/core/ir/access.h" |
| 37 | #include "src/tint/lang/core/ir/binary.h" |
| 38 | #include "src/tint/lang/core/ir/bitcast.h" |
| 39 | #include "src/tint/lang/core/ir/block_param.h" |
| 40 | #include "src/tint/lang/core/ir/break_if.h" |
| 41 | #include "src/tint/lang/core/ir/constant.h" |
| 42 | #include "src/tint/lang/core/ir/construct.h" |
| 43 | #include "src/tint/lang/core/ir/continue.h" |
| 44 | #include "src/tint/lang/core/ir/convert.h" |
| 45 | #include "src/tint/lang/core/ir/core_builtin_call.h" |
| 46 | #include "src/tint/lang/core/ir/discard.h" |
| 47 | #include "src/tint/lang/core/ir/exit_if.h" |
| 48 | #include "src/tint/lang/core/ir/exit_loop.h" |
| 49 | #include "src/tint/lang/core/ir/exit_switch.h" |
| 50 | #include "src/tint/lang/core/ir/function.h" |
| 51 | #include "src/tint/lang/core/ir/function_param.h" |
| 52 | #include "src/tint/lang/core/ir/if.h" |
| 53 | #include "src/tint/lang/core/ir/instruction_result.h" |
dan sinclair | 97c3727 | 2023-07-24 17:11:53 +0000 | [diff] [blame] | 54 | #include "src/tint/lang/core/ir/let.h" |
| 55 | #include "src/tint/lang/core/ir/load.h" |
| 56 | #include "src/tint/lang/core/ir/load_vector_element.h" |
| 57 | #include "src/tint/lang/core/ir/loop.h" |
| 58 | #include "src/tint/lang/core/ir/module.h" |
| 59 | #include "src/tint/lang/core/ir/multi_in_block.h" |
| 60 | #include "src/tint/lang/core/ir/next_iteration.h" |
| 61 | #include "src/tint/lang/core/ir/return.h" |
| 62 | #include "src/tint/lang/core/ir/store.h" |
| 63 | #include "src/tint/lang/core/ir/store_vector_element.h" |
| 64 | #include "src/tint/lang/core/ir/switch.h" |
| 65 | #include "src/tint/lang/core/ir/swizzle.h" |
| 66 | #include "src/tint/lang/core/ir/terminate_invocation.h" |
| 67 | #include "src/tint/lang/core/ir/unary.h" |
| 68 | #include "src/tint/lang/core/ir/unreachable.h" |
| 69 | #include "src/tint/lang/core/ir/user_call.h" |
| 70 | #include "src/tint/lang/core/ir/value.h" |
| 71 | #include "src/tint/lang/core/ir/var.h" |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 72 | #include "src/tint/lang/core/type/array.h" |
dan sinclair | 352f8c8 | 2023-07-21 00:40:07 +0000 | [diff] [blame] | 73 | #include "src/tint/lang/core/type/bool.h" |
| 74 | #include "src/tint/lang/core/type/f16.h" |
| 75 | #include "src/tint/lang/core/type/f32.h" |
| 76 | #include "src/tint/lang/core/type/i32.h" |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 77 | #include "src/tint/lang/core/type/matrix.h" |
dan sinclair | 352f8c8 | 2023-07-21 00:40:07 +0000 | [diff] [blame] | 78 | #include "src/tint/lang/core/type/pointer.h" |
| 79 | #include "src/tint/lang/core/type/u32.h" |
| 80 | #include "src/tint/lang/core/type/vector.h" |
| 81 | #include "src/tint/lang/core/type/void.h" |
Ben Clayton | f848af2 | 2023-07-28 16:37:32 +0000 | [diff] [blame] | 82 | #include "src/tint/utils/ice/ice.h" |
dan sinclair | 22b4dd2 | 2023-07-21 00:40:07 +0000 | [diff] [blame] | 83 | #include "src/tint/utils/macros/scoped_assignment.h" |
| 84 | #include "src/tint/utils/rtti/switch.h" |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 85 | |
dan sinclair | 6f138fe | 2023-08-15 21:29:34 +0000 | [diff] [blame] | 86 | namespace tint::core::ir { |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 87 | |
dan sinclair | 8bcb4e9 | 2023-01-06 19:45:13 +0000 | [diff] [blame] | 88 | /// Builds an ir::Module |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 89 | class Builder { |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 90 | /// Evaluates to true if T is a non-reference instruction pointer. |
| 91 | template <typename T> |
| 92 | static constexpr bool IsNonRefInstPtr = |
| 93 | std::is_pointer_v<T> && std::is_base_of_v<ir::Instruction, std::remove_pointer_t<T>>; |
| 94 | |
| 95 | /// static_assert()s that ARGS contains no more than one non-reference instruction pointer. |
| 96 | /// This is used to detect patterns where C++ non-deterministic evaluation order may cause |
| 97 | /// instruction ordering bugs. |
| 98 | template <typename... ARGS> |
| 99 | static constexpr void CheckForNonDeterministicEvaluation() { |
| 100 | constexpr bool possibly_non_deterministic_eval = |
| 101 | ((IsNonRefInstPtr<ARGS> ? 1 : 0) + ...) > 1; |
| 102 | static_assert(!possibly_non_deterministic_eval, |
| 103 | "Detected possible non-deterministic ordering of instructions. " |
| 104 | "Consider hoisting Builder call arguments to separate statements."); |
| 105 | } |
| 106 | |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 107 | /// A helper used to enable overloads if the first type in `TYPES` is a Vector or |
| 108 | /// VectorRef. |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 109 | template <typename... TYPES> |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 110 | using EnableIfVectorLike = tint::traits::EnableIf< |
| 111 | tint::IsVectorLike<tint::traits::Decay<tint::traits::NthTypeOf<0, TYPES..., void>>>>; |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 112 | |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 113 | /// A helper used to disable overloads if the first type in `TYPES` is a Vector or |
| 114 | /// VectorRef. |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 115 | template <typename... TYPES> |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 116 | using DisableIfVectorLike = tint::traits::EnableIf< |
| 117 | !tint::IsVectorLike<tint::traits::Decay<tint::traits::NthTypeOf<0, TYPES..., void>>>>; |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 118 | |
Ben Clayton | 47fe0f5 | 2023-09-20 07:47:12 +0000 | [diff] [blame] | 119 | /// A namespace for the various instruction insertion method |
| 120 | struct InsertionPoints { |
| 121 | /// Insertion point method that does no insertion |
| 122 | struct NoInsertion { |
| 123 | /// The insertion point function |
| 124 | void operator()(ir::Instruction*) {} |
| 125 | }; |
| 126 | /// Insertion point method that inserts the instruction to the end of #block |
| 127 | struct AppendToBlock { |
| 128 | /// The block to insert new instructions to the end of |
| 129 | ir::Block* block = nullptr; |
| 130 | /// The insertion point function |
| 131 | /// @param i the instruction to insert |
| 132 | void operator()(ir::Instruction* i) { block->Append(i); } |
| 133 | }; |
| 134 | /// Insertion point method that inserts the instruction to the front of #block |
| 135 | struct PrependToBlock { |
| 136 | /// The block to insert new instructions to the front of |
| 137 | ir::Block* block = nullptr; |
| 138 | /// The insertion point function |
| 139 | /// @param i the instruction to insert |
| 140 | void operator()(ir::Instruction* i) { block->Prepend(i); } |
| 141 | }; |
| 142 | /// Insertion point method that inserts the instruction after #after |
| 143 | struct InsertAfter { |
| 144 | /// The instruction to insert new instructions after |
| 145 | ir::Instruction* after = nullptr; |
| 146 | /// The insertion point function |
| 147 | /// @param i the instruction to insert |
| 148 | void operator()(ir::Instruction* i) { i->InsertAfter(after); } |
| 149 | }; |
| 150 | /// Insertion point method that inserts the instruction before #before |
| 151 | struct InsertBefore { |
| 152 | /// The instruction to insert new instructions before |
| 153 | ir::Instruction* before = nullptr; |
| 154 | /// The insertion point function |
| 155 | /// @param i the instruction to insert |
| 156 | void operator()(ir::Instruction* i) { i->InsertBefore(before); } |
| 157 | }; |
| 158 | }; |
dan sinclair | 2ef2311 | 2023-06-14 10:16:53 +0000 | [diff] [blame] | 159 | |
Ben Clayton | 47fe0f5 | 2023-09-20 07:47:12 +0000 | [diff] [blame] | 160 | /// A variant of different instruction insertion methods |
| 161 | using InsertionPoint = std::variant<InsertionPoints::NoInsertion, |
| 162 | InsertionPoints::AppendToBlock, |
| 163 | InsertionPoints::PrependToBlock, |
| 164 | InsertionPoints::InsertAfter, |
| 165 | InsertionPoints::InsertBefore>; |
| 166 | |
| 167 | /// The insertion method used for new instructions. |
| 168 | InsertionPoint insertion_point_{InsertionPoints::NoInsertion{}}; |
James Price | 36b63fd | 2023-07-26 22:07:39 +0000 | [diff] [blame] | 169 | |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 170 | public: |
| 171 | /// Constructor |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 172 | /// @param mod the ir::Module to wrap with this builder |
dan sinclair | 809187c | 2023-05-15 23:42:33 +0000 | [diff] [blame] | 173 | explicit Builder(Module& mod); |
dan sinclair | 2ef2311 | 2023-06-14 10:16:53 +0000 | [diff] [blame] | 174 | /// Constructor |
| 175 | /// @param mod the ir::Module to wrap with this builder |
Ben Clayton | 47fe0f5 | 2023-09-20 07:47:12 +0000 | [diff] [blame] | 176 | /// @param block the block to append to |
dan sinclair | 2ef2311 | 2023-06-14 10:16:53 +0000 | [diff] [blame] | 177 | Builder(Module& mod, ir::Block* block); |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 178 | /// Destructor |
| 179 | ~Builder(); |
| 180 | |
James Price | ecbb3ec | 2023-07-26 22:07:39 +0000 | [diff] [blame] | 181 | /// Creates a new builder that will append to the given block |
| 182 | /// @param b the block to append new instructions to |
dan sinclair | 2ef2311 | 2023-06-14 10:16:53 +0000 | [diff] [blame] | 183 | /// @returns the builder |
James Price | ecbb3ec | 2023-07-26 22:07:39 +0000 | [diff] [blame] | 184 | Builder Append(ir::Block* b) { return Builder(ir, b); } |
Ben Clayton | 26fbdaa | 2023-06-22 20:46:13 +0000 | [diff] [blame] | 185 | |
| 186 | /// Calls @p cb with the builder appending to block @p b |
| 187 | /// @param b the block to set as the block to append to |
| 188 | /// @param cb the function to call with the builder appending to block @p b |
| 189 | template <typename FUNCTION> |
James Price | ecbb3ec | 2023-07-26 22:07:39 +0000 | [diff] [blame] | 190 | void Append(ir::Block* b, FUNCTION&& cb) { |
Ben Clayton | 47fe0f5 | 2023-09-20 07:47:12 +0000 | [diff] [blame] | 191 | TINT_SCOPED_ASSIGNMENT(insertion_point_, InsertionPoints::AppendToBlock{b}); |
| 192 | cb(); |
| 193 | } |
| 194 | |
| 195 | /// Calls @p cb with the builder prepending to block @p b |
| 196 | /// @param b the block to set as the block to prepend to |
| 197 | /// @param cb the function to call with the builder prepending to block @p b |
| 198 | template <typename FUNCTION> |
| 199 | void Prepend(ir::Block* b, FUNCTION&& cb) { |
| 200 | TINT_SCOPED_ASSIGNMENT(insertion_point_, InsertionPoints::PrependToBlock{b}); |
| 201 | cb(); |
| 202 | } |
| 203 | |
| 204 | /// Calls @p cb with the builder inserting after @p ip |
| 205 | /// @param ip the insertion point for new instructions |
| 206 | /// @param cb the function to call with the builder inserting new instructions after @p ip |
| 207 | template <typename FUNCTION> |
| 208 | void InsertAfter(ir::Instruction* ip, FUNCTION&& cb) { |
| 209 | TINT_SCOPED_ASSIGNMENT(insertion_point_, InsertionPoints::InsertAfter{ip}); |
Ben Clayton | 26fbdaa | 2023-06-22 20:46:13 +0000 | [diff] [blame] | 210 | cb(); |
| 211 | } |
dan sinclair | 2ef2311 | 2023-06-14 10:16:53 +0000 | [diff] [blame] | 212 | |
James Price | 36b63fd | 2023-07-26 22:07:39 +0000 | [diff] [blame] | 213 | /// Calls @p cb with the builder inserting before @p ip |
| 214 | /// @param ip the insertion point for new instructions |
| 215 | /// @param cb the function to call with the builder inserting new instructions before @p ip |
| 216 | template <typename FUNCTION> |
| 217 | void InsertBefore(ir::Instruction* ip, FUNCTION&& cb) { |
Ben Clayton | 47fe0f5 | 2023-09-20 07:47:12 +0000 | [diff] [blame] | 218 | TINT_SCOPED_ASSIGNMENT(insertion_point_, InsertionPoints::InsertBefore{ip}); |
James Price | 36b63fd | 2023-07-26 22:07:39 +0000 | [diff] [blame] | 219 | cb(); |
| 220 | } |
| 221 | |
Ben Clayton | 47fe0f5 | 2023-09-20 07:47:12 +0000 | [diff] [blame] | 222 | /// Adds and returns the instruction @p instruction to the current insertion point. If there |
| 223 | /// is no current insertion point set, then @p instruction is just returned. |
| 224 | /// @param instruction the instruction to append |
dan sinclair | 56cb75e | 2023-06-22 16:59:35 +0000 | [diff] [blame] | 225 | /// @returns the instruction |
| 226 | template <typename T> |
Ben Clayton | 47fe0f5 | 2023-09-20 07:47:12 +0000 | [diff] [blame] | 227 | T* Append(T* instruction) { |
| 228 | std::visit([instruction](auto&& mode) { mode(instruction); }, insertion_point_); |
| 229 | return instruction; |
dan sinclair | 56cb75e | 2023-06-22 16:59:35 +0000 | [diff] [blame] | 230 | } |
| 231 | |
Ben Clayton | 0ebf677 | 2023-06-08 11:36:35 +0000 | [diff] [blame] | 232 | /// @returns a new block |
Ben Clayton | c67a4fa | 2023-06-09 19:34:20 +0000 | [diff] [blame] | 233 | ir::Block* Block(); |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 234 | |
Ben Clayton | 0ebf677 | 2023-06-08 11:36:35 +0000 | [diff] [blame] | 235 | /// @returns a new multi-in block |
Ben Clayton | c67a4fa | 2023-06-09 19:34:20 +0000 | [diff] [blame] | 236 | ir::MultiInBlock* MultiInBlock(); |
Ben Clayton | 0ebf677 | 2023-06-08 11:36:35 +0000 | [diff] [blame] | 237 | |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 238 | /// Creates a function instruction |
dan sinclair | c9923d2 | 2023-05-15 23:44:04 +0000 | [diff] [blame] | 239 | /// @param name the function name |
| 240 | /// @param return_type the function return type |
dan sinclair | f59547f | 2023-05-16 14:43:45 +0000 | [diff] [blame] | 241 | /// @param stage the function stage |
| 242 | /// @param wg_size the workgroup_size |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 243 | /// @returns the instruction |
Ben Clayton | c67a4fa | 2023-06-09 19:34:20 +0000 | [diff] [blame] | 244 | ir::Function* Function(std::string_view name, |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 245 | const core::type::Type* return_type, |
Ben Clayton | c67a4fa | 2023-06-09 19:34:20 +0000 | [diff] [blame] | 246 | Function::PipelineStage stage = Function::PipelineStage::kUndefined, |
| 247 | std::optional<std::array<uint32_t, 3>> wg_size = {}); |
dan sinclair | c4722c2 | 2023-05-23 22:28:33 +0000 | [diff] [blame] | 248 | |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 249 | /// Creates an if instruction |
dan sinclair | c9923d2 | 2023-05-15 23:44:04 +0000 | [diff] [blame] | 250 | /// @param condition the if condition |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 251 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 252 | template <typename T> |
| 253 | ir::If* If(T&& condition) { |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 254 | auto* cond_val = Value(std::forward<T>(condition)); |
| 255 | return Append(ir.instructions.Create<ir::If>(cond_val, Block(), Block())); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 256 | } |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 257 | |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 258 | /// Creates a loop instruction |
| 259 | /// @returns the instruction |
Ben Clayton | c67a4fa | 2023-06-09 19:34:20 +0000 | [diff] [blame] | 260 | ir::Loop* Loop(); |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 261 | |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 262 | /// Creates a switch instruction |
dan sinclair | c9923d2 | 2023-05-15 23:44:04 +0000 | [diff] [blame] | 263 | /// @param condition the switch condition |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 264 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 265 | template <typename T> |
| 266 | ir::Switch* Switch(T&& condition) { |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 267 | auto* cond_val = Value(std::forward<T>(condition)); |
| 268 | return Append(ir.instructions.Create<ir::Switch>(cond_val)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 269 | } |
dan sinclair | d336733 | 2022-11-01 14:34:08 +0000 | [diff] [blame] | 270 | |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 271 | /// Creates a case for the switch @p s with the given selectors |
dan sinclair | d336733 | 2022-11-01 14:34:08 +0000 | [diff] [blame] | 272 | /// @param s the switch to create the case into |
| 273 | /// @param selectors the case selectors for the case statement |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 274 | /// @returns the start block for the case instruction |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 275 | ir::Block* Case(ir::Switch* s, VectorRef<Switch::CaseSelector> selectors); |
dan sinclair | d336733 | 2022-11-01 14:34:08 +0000 | [diff] [blame] | 276 | |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 277 | /// Creates a case for the switch @p s with the given selectors |
Ben Clayton | b768af4 | 2023-06-09 23:31:16 +0000 | [diff] [blame] | 278 | /// @param s the switch to create the case into |
| 279 | /// @param selectors the case selectors for the case statement |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 280 | /// @returns the start block for the case instruction |
Ben Clayton | b768af4 | 2023-06-09 23:31:16 +0000 | [diff] [blame] | 281 | ir::Block* Case(ir::Switch* s, std::initializer_list<Switch::CaseSelector> selectors); |
| 282 | |
dan sinclair | 19ebcb2 | 2022-12-15 19:17:22 +0000 | [diff] [blame] | 283 | /// Creates a new ir::Constant |
dan sinclair | e272eaf | 2022-11-29 23:27:46 +0000 | [diff] [blame] | 284 | /// @param val the constant value |
| 285 | /// @returns the new constant |
dan sinclair | 464b3b8 | 2023-08-09 14:14:28 +0000 | [diff] [blame] | 286 | ir::Constant* Constant(const core::constant::Value* val) { |
Ben Clayton | a0aabaf | 2023-06-22 23:53:09 +0000 | [diff] [blame] | 287 | return ir.constants.GetOrCreate(val, [&] { return ir.values.Create<ir::Constant>(val); }); |
dan sinclair | 2d108ae | 2022-11-29 20:36:59 +0000 | [diff] [blame] | 288 | } |
| 289 | |
dan sinclair | 19ebcb2 | 2022-12-15 19:17:22 +0000 | [diff] [blame] | 290 | /// Creates a ir::Constant for an i32 Scalar |
| 291 | /// @param v the value |
| 292 | /// @returns the new constant |
dan sinclair | ce6dffe | 2023-08-14 21:01:40 +0000 | [diff] [blame] | 293 | ir::Constant* Constant(core::i32 v) { return Constant(ConstantValue(v)); } |
dan sinclair | 19ebcb2 | 2022-12-15 19:17:22 +0000 | [diff] [blame] | 294 | |
| 295 | /// Creates a ir::Constant for a u32 Scalar |
| 296 | /// @param v the value |
| 297 | /// @returns the new constant |
dan sinclair | ce6dffe | 2023-08-14 21:01:40 +0000 | [diff] [blame] | 298 | ir::Constant* Constant(core::u32 v) { return Constant(ConstantValue(v)); } |
dan sinclair | 19ebcb2 | 2022-12-15 19:17:22 +0000 | [diff] [blame] | 299 | |
| 300 | /// Creates a ir::Constant for a f32 Scalar |
| 301 | /// @param v the value |
| 302 | /// @returns the new constant |
dan sinclair | ce6dffe | 2023-08-14 21:01:40 +0000 | [diff] [blame] | 303 | ir::Constant* Constant(core::f32 v) { return Constant(ConstantValue(v)); } |
dan sinclair | 19ebcb2 | 2022-12-15 19:17:22 +0000 | [diff] [blame] | 304 | |
| 305 | /// Creates a ir::Constant for a f16 Scalar |
| 306 | /// @param v the value |
| 307 | /// @returns the new constant |
dan sinclair | ce6dffe | 2023-08-14 21:01:40 +0000 | [diff] [blame] | 308 | ir::Constant* Constant(core::f16 v) { return Constant(ConstantValue(v)); } |
dan sinclair | 19ebcb2 | 2022-12-15 19:17:22 +0000 | [diff] [blame] | 309 | |
| 310 | /// Creates a ir::Constant for a bool Scalar |
| 311 | /// @param v the value |
| 312 | /// @returns the new constant |
Ben Clayton | 6d3bf1a | 2023-07-11 15:10:09 +0000 | [diff] [blame] | 313 | template <typename BOOL, typename = std::enable_if_t<std::is_same_v<BOOL, bool>>> |
| 314 | ir::Constant* Constant(BOOL v) { |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 315 | return Constant(ConstantValue(v)); |
| 316 | } |
| 317 | |
| 318 | /// Retrieves the inner constant from an ir::Constant |
| 319 | /// @param constant the ir constant |
dan sinclair | 464b3b8 | 2023-08-09 14:14:28 +0000 | [diff] [blame] | 320 | /// @returns the core::constant::Value inside the constant |
| 321 | const core::constant::Value* ConstantValue(ir::Constant* constant) { return constant->Value(); } |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 322 | |
dan sinclair | 464b3b8 | 2023-08-09 14:14:28 +0000 | [diff] [blame] | 323 | /// Creates a core::constant::Value for an i32 Scalar |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 324 | /// @param v the value |
| 325 | /// @returns the new constant |
dan sinclair | ce6dffe | 2023-08-14 21:01:40 +0000 | [diff] [blame] | 326 | const core::constant::Value* ConstantValue(core::i32 v) { return ir.constant_values.Get(v); } |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 327 | |
dan sinclair | 464b3b8 | 2023-08-09 14:14:28 +0000 | [diff] [blame] | 328 | /// Creates a core::constant::Value for a u32 Scalar |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 329 | /// @param v the value |
| 330 | /// @returns the new constant |
dan sinclair | ce6dffe | 2023-08-14 21:01:40 +0000 | [diff] [blame] | 331 | const core::constant::Value* ConstantValue(core::u32 v) { return ir.constant_values.Get(v); } |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 332 | |
dan sinclair | 464b3b8 | 2023-08-09 14:14:28 +0000 | [diff] [blame] | 333 | /// Creates a core::constant::Value for a f32 Scalar |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 334 | /// @param v the value |
| 335 | /// @returns the new constant |
dan sinclair | ce6dffe | 2023-08-14 21:01:40 +0000 | [diff] [blame] | 336 | const core::constant::Value* ConstantValue(core::f32 v) { return ir.constant_values.Get(v); } |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 337 | |
dan sinclair | 464b3b8 | 2023-08-09 14:14:28 +0000 | [diff] [blame] | 338 | /// Creates a core::constant::Value for a f16 Scalar |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 339 | /// @param v the value |
| 340 | /// @returns the new constant |
dan sinclair | ce6dffe | 2023-08-14 21:01:40 +0000 | [diff] [blame] | 341 | const core::constant::Value* ConstantValue(core::f16 v) { return ir.constant_values.Get(v); } |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 342 | |
dan sinclair | 464b3b8 | 2023-08-09 14:14:28 +0000 | [diff] [blame] | 343 | /// Creates a core::constant::Value for a bool Scalar |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 344 | /// @param v the value |
| 345 | /// @returns the new constant |
| 346 | template <typename BOOL, typename = std::enable_if_t<std::is_same_v<BOOL, bool>>> |
dan sinclair | 464b3b8 | 2023-08-09 14:14:28 +0000 | [diff] [blame] | 347 | const core::constant::Value* ConstantValue(BOOL v) { |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 348 | return ir.constant_values.Get(v); |
| 349 | } |
| 350 | |
| 351 | /// Creates a new ir::Constant |
dan sinclair | 23314ca | 2023-08-03 16:02:22 +0000 | [diff] [blame] | 352 | /// @param ty the splat type |
| 353 | /// @param value the splat value |
| 354 | /// @param size the number of items |
| 355 | /// @returns the new constant |
| 356 | template <typename ARG> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 357 | ir::Constant* Splat(const core::type::Type* ty, ARG&& value, size_t size) { |
dan sinclair | 23314ca | 2023-08-03 16:02:22 +0000 | [diff] [blame] | 358 | return Constant( |
| 359 | ir.constant_values.Splat(ty, ConstantValue(std::forward<ARG>(value)), size)); |
| 360 | } |
| 361 | |
| 362 | /// Creates a new ir::Constant |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 363 | /// @param ty the constant type |
| 364 | /// @param values the composite values |
| 365 | /// @returns the new constant |
| 366 | template <typename... ARGS, typename = DisableIfVectorLike<ARGS...>> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 367 | ir::Constant* Composite(const core::type::Type* ty, ARGS&&... values) { |
dan sinclair | 34e0342 | 2023-08-02 20:42:41 +0000 | [diff] [blame] | 368 | return Constant( |
| 369 | ir.constant_values.Composite(ty, Vector{ConstantValue(std::forward<ARGS>(values))...})); |
Ben Clayton | 6d3bf1a | 2023-07-11 15:10:09 +0000 | [diff] [blame] | 370 | } |
dan sinclair | 19ebcb2 | 2022-12-15 19:17:22 +0000 | [diff] [blame] | 371 | |
James Price | dcf6c42 | 2023-09-29 20:48:34 +0000 | [diff] [blame] | 372 | /// Creates a new zero-value ir::Constant |
| 373 | /// @param ty the constant type |
| 374 | /// @returns the new constant |
| 375 | ir::Constant* Zero(const core::type::Type* ty) { return Constant(ir.constant_values.Zero(ty)); } |
| 376 | |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 377 | /// @param in the input value. One of: nullptr, ir::Value*, ir::Instruction* or a numeric value. |
| 378 | /// @returns an ir::Value* from the given argument. |
dan sinclair | 0d80c3d | 2023-06-19 13:32:03 +0000 | [diff] [blame] | 379 | template <typename T> |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 380 | ir::Value* Value(T&& in) { |
| 381 | using D = std::decay_t<T>; |
| 382 | constexpr bool is_null = std::is_same_v<T, std::nullptr_t>; |
| 383 | constexpr bool is_ptr = std::is_pointer_v<D>; |
dan sinclair | ce6dffe | 2023-08-14 21:01:40 +0000 | [diff] [blame] | 384 | constexpr bool is_numeric = core::IsNumeric<D>; |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 385 | static_assert(is_null || is_ptr || is_numeric, "invalid argument type for Value()"); |
| 386 | |
| 387 | if constexpr (is_null) { |
| 388 | return nullptr; |
| 389 | } else if constexpr (is_ptr) { |
| 390 | using P = std::remove_pointer_t<D>; |
| 391 | constexpr bool is_value = std::is_base_of_v<ir::Value, P>; |
| 392 | constexpr bool is_instruction = std::is_base_of_v<ir::Instruction, P>; |
| 393 | static_assert(is_value || is_instruction, "invalid pointer type for Value()"); |
| 394 | |
| 395 | if constexpr (is_value) { |
| 396 | return in; /// Pass-through |
| 397 | } else if constexpr (is_instruction) { |
| 398 | /// Extract the first result from the instruction |
Ben Clayton | f848af2 | 2023-07-28 16:37:32 +0000 | [diff] [blame] | 399 | TINT_ASSERT(in->HasResults() && !in->HasMultiResults()); |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 400 | return in->Result(); |
| 401 | } |
| 402 | } else if constexpr (is_numeric) { |
| 403 | /// Creates a value from the given number |
| 404 | return Constant(in); |
| 405 | } |
dan sinclair | 0d80c3d | 2023-06-19 13:32:03 +0000 | [diff] [blame] | 406 | } |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 407 | |
| 408 | /// Pass-through overload for Values() with vector-like argument |
| 409 | /// @param vec the vector of ir::Value* |
| 410 | /// @return @p vec |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 411 | template <typename VEC, typename = EnableIfVectorLike<tint::traits::Decay<VEC>>> |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 412 | auto Values(VEC&& vec) { |
| 413 | return std::forward<VEC>(vec); |
| 414 | } |
| 415 | |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 416 | /// Overload for Values() with tint::Empty argument |
| 417 | /// @return tint::Empty |
| 418 | tint::EmptyType Values(tint::EmptyType) { return tint::Empty; } |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 419 | |
| 420 | /// Overload for Values() with no arguments |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 421 | /// @return tint::Empty |
| 422 | tint::EmptyType Values() { return tint::Empty; } |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 423 | |
| 424 | /// @param args the arguments to pass to Value() |
| 425 | /// @returns a vector of ir::Value* built from transforming the arguments with Value() |
| 426 | template <typename... ARGS, typename = DisableIfVectorLike<ARGS...>> |
| 427 | auto Values(ARGS&&... args) { |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 428 | CheckForNonDeterministicEvaluation<ARGS...>(); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 429 | return Vector{Value(std::forward<ARGS>(args))...}; |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 430 | } |
| 431 | |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 432 | /// Creates an op for `lhs kind rhs` |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 433 | /// @param op the binary operator |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 434 | /// @param type the result type of the binary expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 435 | /// @param lhs the left-hand-side of the operation |
| 436 | /// @param rhs the right-hand-side of the operation |
| 437 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 438 | template <typename LHS, typename RHS> |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 439 | ir::Binary* Binary(BinaryOp op, const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 440 | CheckForNonDeterministicEvaluation<LHS, RHS>(); |
| 441 | auto* lhs_val = Value(std::forward<LHS>(lhs)); |
| 442 | auto* rhs_val = Value(std::forward<RHS>(rhs)); |
| 443 | return Append( |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 444 | ir.instructions.Create<ir::Binary>(InstructionResult(type), op, lhs_val, rhs_val)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 445 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 446 | |
| 447 | /// Creates an And operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 448 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 449 | /// @param lhs the lhs of the add |
| 450 | /// @param rhs the rhs of the add |
| 451 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 452 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 453 | ir::Binary* And(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 454 | return Binary(BinaryOp::kAnd, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 455 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 456 | |
| 457 | /// Creates an Or operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 458 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 459 | /// @param lhs the lhs of the add |
| 460 | /// @param rhs the rhs of the add |
| 461 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 462 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 463 | ir::Binary* Or(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 464 | return Binary(BinaryOp::kOr, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 465 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 466 | |
| 467 | /// Creates an Xor operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 468 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 469 | /// @param lhs the lhs of the add |
| 470 | /// @param rhs the rhs of the add |
| 471 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 472 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 473 | ir::Binary* Xor(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 474 | return Binary(BinaryOp::kXor, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 475 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 476 | |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 477 | /// Creates an Equal operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 478 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 479 | /// @param lhs the lhs of the add |
| 480 | /// @param rhs the rhs of the add |
| 481 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 482 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 483 | ir::Binary* Equal(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 484 | return Binary(BinaryOp::kEqual, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 485 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 486 | |
| 487 | /// Creates an NotEqual operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 488 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 489 | /// @param lhs the lhs of the add |
| 490 | /// @param rhs the rhs of the add |
| 491 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 492 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 493 | ir::Binary* NotEqual(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 494 | return Binary(BinaryOp::kNotEqual, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 495 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 496 | |
| 497 | /// Creates an LessThan operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 498 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 499 | /// @param lhs the lhs of the add |
| 500 | /// @param rhs the rhs of the add |
| 501 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 502 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 503 | ir::Binary* LessThan(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 504 | return Binary(BinaryOp::kLessThan, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 505 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 506 | |
| 507 | /// Creates an GreaterThan operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 508 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 509 | /// @param lhs the lhs of the add |
| 510 | /// @param rhs the rhs of the add |
| 511 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 512 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 513 | ir::Binary* GreaterThan(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 514 | return Binary(BinaryOp::kGreaterThan, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 515 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 516 | |
| 517 | /// Creates an LessThanEqual operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 518 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 519 | /// @param lhs the lhs of the add |
| 520 | /// @param rhs the rhs of the add |
| 521 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 522 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 523 | ir::Binary* LessThanEqual(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 524 | return Binary(BinaryOp::kLessThanEqual, type, std::forward<LHS>(lhs), |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 525 | std::forward<RHS>(rhs)); |
| 526 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 527 | |
| 528 | /// Creates an GreaterThanEqual operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 529 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 530 | /// @param lhs the lhs of the add |
| 531 | /// @param rhs the rhs of the add |
| 532 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 533 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 534 | ir::Binary* GreaterThanEqual(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 535 | return Binary(BinaryOp::kGreaterThanEqual, type, std::forward<LHS>(lhs), |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 536 | std::forward<RHS>(rhs)); |
| 537 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 538 | |
| 539 | /// Creates an ShiftLeft operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 540 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 541 | /// @param lhs the lhs of the add |
| 542 | /// @param rhs the rhs of the add |
| 543 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 544 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 545 | ir::Binary* ShiftLeft(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 546 | return Binary(BinaryOp::kShiftLeft, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 547 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 548 | |
| 549 | /// Creates an ShiftRight operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 550 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 551 | /// @param lhs the lhs of the add |
| 552 | /// @param rhs the rhs of the add |
| 553 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 554 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 555 | ir::Binary* ShiftRight(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 556 | return Binary(BinaryOp::kShiftRight, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 557 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 558 | |
| 559 | /// Creates an Add operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 560 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 561 | /// @param lhs the lhs of the add |
| 562 | /// @param rhs the rhs of the add |
| 563 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 564 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 565 | ir::Binary* Add(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 566 | return Binary(BinaryOp::kAdd, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 567 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 568 | |
| 569 | /// Creates an Subtract operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 570 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 571 | /// @param lhs the lhs of the add |
| 572 | /// @param rhs the rhs of the add |
| 573 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 574 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 575 | ir::Binary* Subtract(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 576 | return Binary(BinaryOp::kSubtract, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 577 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 578 | |
| 579 | /// Creates an Multiply operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 580 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 581 | /// @param lhs the lhs of the add |
| 582 | /// @param rhs the rhs of the add |
| 583 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 584 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 585 | ir::Binary* Multiply(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 586 | return Binary(BinaryOp::kMultiply, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 587 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 588 | |
| 589 | /// Creates an Divide operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 590 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 591 | /// @param lhs the lhs of the add |
| 592 | /// @param rhs the rhs of the add |
| 593 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 594 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 595 | ir::Binary* Divide(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 596 | return Binary(BinaryOp::kDivide, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 597 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 598 | |
| 599 | /// Creates an Modulo operation |
dan sinclair | 3e449f2 | 2023-01-03 20:25:13 +0000 | [diff] [blame] | 600 | /// @param type the result type of the expression |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 601 | /// @param lhs the lhs of the add |
| 602 | /// @param rhs the rhs of the add |
| 603 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 604 | template <typename LHS, typename RHS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 605 | ir::Binary* Modulo(const core::type::Type* type, LHS&& lhs, RHS&& rhs) { |
Ben Clayton | eee2a83 | 2023-10-17 17:33:03 +0000 | [diff] [blame] | 606 | return Binary(BinaryOp::kModulo, type, std::forward<LHS>(lhs), std::forward<RHS>(rhs)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 607 | } |
dan sinclair | 669e15e | 2022-11-23 02:11:52 +0000 | [diff] [blame] | 608 | |
Ben Clayton | f7055d7 | 2023-10-21 01:39:08 +0000 | [diff] [blame] | 609 | /// Creates an op for `op val` |
| 610 | /// @param op the unary operator |
dan sinclair | 5aa7ef2 | 2023-04-26 00:08:35 +0000 | [diff] [blame] | 611 | /// @param type the result type of the binary expression |
| 612 | /// @param val the value of the operation |
| 613 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 614 | template <typename VAL> |
Ben Clayton | f7055d7 | 2023-10-21 01:39:08 +0000 | [diff] [blame] | 615 | ir::Unary* Unary(UnaryOp op, const core::type::Type* type, VAL&& val) { |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 616 | auto* value = Value(std::forward<VAL>(val)); |
Ben Clayton | f7055d7 | 2023-10-21 01:39:08 +0000 | [diff] [blame] | 617 | return Append(ir.instructions.Create<ir::Unary>(InstructionResult(type), op, value)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 618 | } |
dan sinclair | 5aa7ef2 | 2023-04-26 00:08:35 +0000 | [diff] [blame] | 619 | |
dan sinclair | 5aa7ef2 | 2023-04-26 00:08:35 +0000 | [diff] [blame] | 620 | /// Creates a Complement operation |
| 621 | /// @param type the result type of the expression |
| 622 | /// @param val the value |
| 623 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 624 | template <typename VAL> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 625 | ir::Unary* Complement(const core::type::Type* type, VAL&& val) { |
Ben Clayton | f7055d7 | 2023-10-21 01:39:08 +0000 | [diff] [blame] | 626 | return Unary(ir::UnaryOp::kComplement, type, std::forward<VAL>(val)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 627 | } |
dan sinclair | 5aa7ef2 | 2023-04-26 00:08:35 +0000 | [diff] [blame] | 628 | |
dan sinclair | 5aa7ef2 | 2023-04-26 00:08:35 +0000 | [diff] [blame] | 629 | /// Creates a Negation operation |
| 630 | /// @param type the result type of the expression |
| 631 | /// @param val the value |
| 632 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 633 | template <typename VAL> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 634 | ir::Unary* Negation(const core::type::Type* type, VAL&& val) { |
Ben Clayton | f7055d7 | 2023-10-21 01:39:08 +0000 | [diff] [blame] | 635 | return Unary(ir::UnaryOp::kNegation, type, std::forward<VAL>(val)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 636 | } |
dan sinclair | 5aa7ef2 | 2023-04-26 00:08:35 +0000 | [diff] [blame] | 637 | |
| 638 | /// Creates a Not operation |
| 639 | /// @param type the result type of the expression |
| 640 | /// @param val the value |
| 641 | /// @returns the operation |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 642 | template <typename VAL> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 643 | ir::Binary* Not(const core::type::Type* type, VAL&& val) { |
| 644 | if (auto* vec = type->As<core::type::Vector>()) { |
dan sinclair | 23314ca | 2023-08-03 16:02:22 +0000 | [diff] [blame] | 645 | return Equal(type, std::forward<VAL>(val), Splat(vec, false, vec->Width())); |
James Price | 57c4629 | 2023-07-14 16:30:28 +0000 | [diff] [blame] | 646 | } else { |
| 647 | return Equal(type, std::forward<VAL>(val), Constant(false)); |
| 648 | } |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 649 | } |
dan sinclair | 5aa7ef2 | 2023-04-26 00:08:35 +0000 | [diff] [blame] | 650 | |
dan sinclair | 4cef436 | 2023-01-03 20:29:43 +0000 | [diff] [blame] | 651 | /// Creates a bitcast instruction |
| 652 | /// @param type the result type of the bitcast |
| 653 | /// @param val the value being bitcast |
| 654 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 655 | template <typename VAL> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 656 | ir::Bitcast* Bitcast(const core::type::Type* type, VAL&& val) { |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 657 | auto* value = Value(std::forward<VAL>(val)); |
| 658 | return Append(ir.instructions.Create<ir::Bitcast>(InstructionResult(type), value)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 659 | } |
dan sinclair | 4cef436 | 2023-01-03 20:29:43 +0000 | [diff] [blame] | 660 | |
dan sinclair | 69108d0 | 2023-04-25 20:44:18 +0000 | [diff] [blame] | 661 | /// Creates a discard instruction |
| 662 | /// @returns the instruction |
| 663 | ir::Discard* Discard(); |
| 664 | |
dan sinclair | 724a70f | 2023-03-08 21:19:13 +0000 | [diff] [blame] | 665 | /// Creates a user function call instruction |
Ben Clayton | 5021631 | 2023-09-25 15:38:43 +0000 | [diff] [blame] | 666 | /// @param func the function to call |
| 667 | /// @param args the call arguments |
| 668 | /// @returns the instruction |
| 669 | template <typename... ARGS> |
| 670 | ir::UserCall* Call(ir::Function* func, ARGS&&... args) { |
| 671 | return Call(func->ReturnType(), func, std::forward<ARGS>(args)...); |
| 672 | } |
| 673 | |
| 674 | /// Creates a user function call instruction |
dan sinclair | 724a70f | 2023-03-08 21:19:13 +0000 | [diff] [blame] | 675 | /// @param type the return type of the call |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 676 | /// @param func the function to call |
dan sinclair | 724a70f | 2023-03-08 21:19:13 +0000 | [diff] [blame] | 677 | /// @param args the call arguments |
| 678 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 679 | template <typename... ARGS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 680 | ir::UserCall* Call(const core::type::Type* type, ir::Function* func, ARGS&&... args) { |
dan sinclair | 0d80c3d | 2023-06-19 13:32:03 +0000 | [diff] [blame] | 681 | return Append(ir.instructions.Create<ir::UserCall>(InstructionResult(type), func, |
| 682 | Values(std::forward<ARGS>(args)...))); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 683 | } |
Ben Clayton | 1d0ac04 | 2023-06-09 16:53:12 +0000 | [diff] [blame] | 684 | |
dan sinclair | ffb4588 | 2023-07-13 22:10:41 +0000 | [diff] [blame] | 685 | /// Creates a core builtin call instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 686 | /// @param type the return type of the call |
| 687 | /// @param func the builtin function to call |
Ben Clayton | 1d0ac04 | 2023-06-09 16:53:12 +0000 | [diff] [blame] | 688 | /// @param args the call arguments |
| 689 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 690 | template <typename... ARGS> |
Ben Clayton | d9766dc | 2023-09-21 12:41:20 +0000 | [diff] [blame] | 691 | ir::CoreBuiltinCall* Call(const core::type::Type* type, core::BuiltinFn func, ARGS&&... args) { |
dan sinclair | ffb4588 | 2023-07-13 22:10:41 +0000 | [diff] [blame] | 692 | return Append(ir.instructions.Create<ir::CoreBuiltinCall>( |
| 693 | InstructionResult(type), func, Values(std::forward<ARGS>(args)...))); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 694 | } |
dan sinclair | 724a70f | 2023-03-08 21:19:13 +0000 | [diff] [blame] | 695 | |
dan sinclair | 774b6a4 | 2023-09-06 21:04:30 +0000 | [diff] [blame] | 696 | /// Creates a core builtin call instruction |
| 697 | /// @param type the return type of the call |
| 698 | /// @param func the builtin function to call |
| 699 | /// @param args the call arguments |
| 700 | /// @returns the instruction |
| 701 | template <typename KLASS, typename FUNC, typename... ARGS> |
| 702 | tint::traits::EnableIf<tint::traits::IsTypeOrDerived<KLASS, ir::BuiltinCall>, KLASS*> |
| 703 | Call(const core::type::Type* type, FUNC func, ARGS&&... args) { |
| 704 | return Append(ir.instructions.Create<KLASS>(InstructionResult(type), func, |
| 705 | Values(std::forward<ARGS>(args)...))); |
| 706 | } |
| 707 | |
Ben Clayton | 5021631 | 2023-09-25 15:38:43 +0000 | [diff] [blame] | 708 | /// Creates a value conversion instruction to the template type T |
| 709 | /// @param val the value to be converted |
| 710 | /// @returns the instruction |
| 711 | template <typename T, typename VAL> |
| 712 | ir::Convert* Convert(VAL&& val) { |
| 713 | auto* type = ir.Types().Get<T>(); |
| 714 | return Convert(type, std::forward<VAL>(val)); |
| 715 | } |
| 716 | |
dan sinclair | 724a70f | 2023-03-08 21:19:13 +0000 | [diff] [blame] | 717 | /// Creates a value conversion instruction |
| 718 | /// @param to the type converted to |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 719 | /// @param val the value to be converted |
dan sinclair | 724a70f | 2023-03-08 21:19:13 +0000 | [diff] [blame] | 720 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 721 | template <typename VAL> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 722 | ir::Convert* Convert(const core::type::Type* to, VAL&& val) { |
dan sinclair | 0d80c3d | 2023-06-19 13:32:03 +0000 | [diff] [blame] | 723 | return Append(ir.instructions.Create<ir::Convert>(InstructionResult(to), |
| 724 | Value(std::forward<VAL>(val)))); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 725 | } |
dan sinclair | 724a70f | 2023-03-08 21:19:13 +0000 | [diff] [blame] | 726 | |
Ben Clayton | 5021631 | 2023-09-25 15:38:43 +0000 | [diff] [blame] | 727 | /// Creates a value constructor instruction to the template type T |
| 728 | /// @param args the arguments to the constructor |
| 729 | /// @returns the instruction |
| 730 | template <typename T, typename... ARGS> |
| 731 | ir::Construct* Construct(ARGS&&... args) { |
| 732 | auto* type = ir.Types().Get<T>(); |
| 733 | return Construct(type, std::forward<ARGS>(args)...); |
| 734 | } |
| 735 | |
dan sinclair | 724a70f | 2023-03-08 21:19:13 +0000 | [diff] [blame] | 736 | /// Creates a value constructor instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 737 | /// @param type the type to constructed |
Ben Clayton | 4abe1b0 | 2023-06-09 18:20:18 +0000 | [diff] [blame] | 738 | /// @param args the arguments to the constructor |
dan sinclair | 724a70f | 2023-03-08 21:19:13 +0000 | [diff] [blame] | 739 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 740 | template <typename... ARGS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 741 | ir::Construct* Construct(const core::type::Type* type, ARGS&&... args) { |
dan sinclair | 0d80c3d | 2023-06-19 13:32:03 +0000 | [diff] [blame] | 742 | return Append(ir.instructions.Create<ir::Construct>(InstructionResult(type), |
| 743 | Values(std::forward<ARGS>(args)...))); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 744 | } |
dan sinclair | 724a70f | 2023-03-08 21:19:13 +0000 | [diff] [blame] | 745 | |
James Price | 90b8cc1 | 2023-05-17 18:41:27 +0000 | [diff] [blame] | 746 | /// Creates a load instruction |
| 747 | /// @param from the expression being loaded from |
| 748 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 749 | template <typename VAL> |
| 750 | ir::Load* Load(VAL&& from) { |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 751 | auto* value = Value(std::forward<VAL>(from)); |
dan sinclair | 0d80c3d | 2023-06-19 13:32:03 +0000 | [diff] [blame] | 752 | return Append( |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 753 | ir.instructions.Create<ir::Load>(InstructionResult(value->Type()->UnwrapPtr()), value)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 754 | } |
James Price | 90b8cc1 | 2023-05-17 18:41:27 +0000 | [diff] [blame] | 755 | |
| 756 | /// Creates a store instruction |
dan sinclair | aa97bb5 | 2023-04-26 00:15:31 +0000 | [diff] [blame] | 757 | /// @param to the expression being stored too |
| 758 | /// @param from the expression being stored |
| 759 | /// @returns the instruction |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 760 | template <typename TO, typename FROM> |
| 761 | ir::Store* Store(TO&& to, FROM&& from) { |
| 762 | CheckForNonDeterministicEvaluation<TO, FROM>(); |
| 763 | auto* to_val = Value(std::forward<TO>(to)); |
| 764 | auto* from_val = Value(std::forward<FROM>(from)); |
| 765 | return Append(ir.instructions.Create<ir::Store>(to_val, from_val)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 766 | } |
dan sinclair | aa97bb5 | 2023-04-26 00:15:31 +0000 | [diff] [blame] | 767 | |
Ben Clayton | a8fce7c | 2023-07-12 18:39:00 +0000 | [diff] [blame] | 768 | /// Creates a store vector element instruction |
| 769 | /// @param to the vector pointer expression being stored too |
| 770 | /// @param index the new vector element index |
| 771 | /// @param value the new vector element expression |
| 772 | /// @returns the instruction |
| 773 | template <typename TO, typename INDEX, typename VALUE> |
| 774 | ir::StoreVectorElement* StoreVectorElement(TO&& to, INDEX&& index, VALUE&& value) { |
| 775 | CheckForNonDeterministicEvaluation<TO, INDEX, VALUE>(); |
| 776 | auto* to_val = Value(std::forward<TO>(to)); |
| 777 | auto* index_val = Value(std::forward<INDEX>(index)); |
| 778 | auto* value_val = Value(std::forward<VALUE>(value)); |
| 779 | return Append(ir.instructions.Create<ir::StoreVectorElement>(to_val, index_val, value_val)); |
| 780 | } |
| 781 | |
| 782 | /// Creates a load vector element instruction |
| 783 | /// @param from the vector pointer expression being loaded from |
| 784 | /// @param index the new vector element index |
| 785 | /// @returns the instruction |
| 786 | template <typename FROM, typename INDEX> |
| 787 | ir::LoadVectorElement* LoadVectorElement(FROM&& from, INDEX&& index) { |
| 788 | CheckForNonDeterministicEvaluation<FROM, INDEX>(); |
| 789 | auto* from_val = Value(std::forward<FROM>(from)); |
| 790 | auto* index_val = Value(std::forward<INDEX>(index)); |
| 791 | auto* res = InstructionResult(VectorPtrElementType(from_val->Type())); |
| 792 | return Append(ir.instructions.Create<ir::LoadVectorElement>(res, from_val, index_val)); |
| 793 | } |
| 794 | |
dan sinclair | c970e80 | 2023-05-02 15:47:29 +0000 | [diff] [blame] | 795 | /// Creates a new `var` declaration |
| 796 | /// @param type the var type |
dan sinclair | c970e80 | 2023-05-02 15:47:29 +0000 | [diff] [blame] | 797 | /// @returns the instruction |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 798 | ir::Var* Var(const core::type::Pointer* type); |
dan sinclair | c970e80 | 2023-05-02 15:47:29 +0000 | [diff] [blame] | 799 | |
James Price | 5448235 | 2023-06-28 16:21:18 +0000 | [diff] [blame] | 800 | /// Creates a new `var` declaration with a name |
| 801 | /// @param name the var name |
| 802 | /// @param type the var type |
| 803 | /// @returns the instruction |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 804 | ir::Var* Var(std::string_view name, const core::type::Pointer* type); |
James Price | 5448235 | 2023-06-28 16:21:18 +0000 | [diff] [blame] | 805 | |
Ben Clayton | 5021631 | 2023-09-25 15:38:43 +0000 | [diff] [blame] | 806 | /// Creates a new `var` declaration with a name and initializer value |
Ben Clayton | fc75496 | 2023-09-26 07:12:46 +0000 | [diff] [blame] | 807 | /// @tparam SPACE the var's address space |
| 808 | /// @tparam ACCESS the var's access mode |
Ben Clayton | 5021631 | 2023-09-25 15:38:43 +0000 | [diff] [blame] | 809 | /// @param name the var name |
| 810 | /// @param init the var initializer |
| 811 | /// @returns the instruction |
| 812 | template <core::AddressSpace SPACE = core::AddressSpace::kFunction, |
| 813 | core::Access ACCESS = core::Access::kReadWrite, |
| 814 | typename VALUE = void> |
| 815 | ir::Var* Var(std::string_view name, VALUE&& init) { |
| 816 | auto* val = Value(std::forward<VALUE>(init)); |
| 817 | if (TINT_UNLIKELY(!val)) { |
| 818 | TINT_ASSERT(val); |
| 819 | return nullptr; |
| 820 | } |
| 821 | auto* var = Var(name, ir.Types().ptr(SPACE, val->Type(), ACCESS)); |
| 822 | var->SetInitializer(val); |
| 823 | ir.SetName(var->Result(), name); |
| 824 | return var; |
| 825 | } |
| 826 | |
Ben Clayton | fc75496 | 2023-09-26 07:12:46 +0000 | [diff] [blame] | 827 | /// Creates a new `var` declaration |
| 828 | /// @tparam SPACE the var's address space |
| 829 | /// @tparam T the storage pointer's element type |
| 830 | /// @tparam ACCESS the var's access mode |
| 831 | /// @returns the instruction |
| 832 | template <core::AddressSpace SPACE, typename T, core::Access ACCESS = core::Access::kReadWrite> |
| 833 | ir::Var* Var() { |
| 834 | return Var(ir.Types().ptr<SPACE, T, ACCESS>()); |
| 835 | } |
| 836 | |
| 837 | /// Creates a new `var` declaration with a name |
| 838 | /// @tparam SPACE the var's address space |
| 839 | /// @tparam T the storage pointer's element type |
| 840 | /// @tparam ACCESS the var's access mode |
| 841 | /// @param name the var name |
| 842 | /// @returns the instruction |
| 843 | template <core::AddressSpace SPACE, typename T, core::Access ACCESS = core::Access::kReadWrite> |
| 844 | ir::Var* Var(std::string_view name) { |
Ben Clayton | a1de3cc | 2023-09-26 17:43:06 +0000 | [diff] [blame] | 845 | return Var(name, ir.Types().ptr<SPACE, T, ACCESS>()); |
Ben Clayton | fc75496 | 2023-09-26 07:12:46 +0000 | [diff] [blame] | 846 | } |
| 847 | |
Ben Clayton | 56343fe | 2023-07-11 09:01:04 +0000 | [diff] [blame] | 848 | /// Creates a new `let` declaration |
| 849 | /// @param name the let name |
| 850 | /// @param value the let value |
| 851 | /// @returns the instruction |
| 852 | template <typename VALUE> |
| 853 | ir::Let* Let(std::string_view name, VALUE&& value) { |
| 854 | auto* val = Value(std::forward<VALUE>(value)); |
| 855 | if (TINT_UNLIKELY(!val)) { |
Ben Clayton | f848af2 | 2023-07-28 16:37:32 +0000 | [diff] [blame] | 856 | TINT_ASSERT(val); |
Ben Clayton | 56343fe | 2023-07-11 09:01:04 +0000 | [diff] [blame] | 857 | return nullptr; |
| 858 | } |
| 859 | auto* let = Append(ir.instructions.Create<ir::Let>(InstructionResult(val->Type()), val)); |
Ben Clayton | 56343fe | 2023-07-11 09:01:04 +0000 | [diff] [blame] | 860 | ir.SetName(let->Result(), name); |
| 861 | return let; |
| 862 | } |
| 863 | |
dan sinclair | 68a8b09 | 2023-05-26 04:31:50 +0000 | [diff] [blame] | 864 | /// Creates a return instruction |
| 865 | /// @param func the function being returned |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 866 | /// @returns the instruction |
dan sinclair | 367fad8 | 2023-06-19 12:58:53 +0000 | [diff] [blame] | 867 | ir::Return* Return(ir::Function* func) { |
| 868 | return Append(ir.instructions.Create<ir::Return>(func)); |
| 869 | } |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 870 | |
| 871 | /// Creates a return instruction |
| 872 | /// @param func the function being returned |
James Price | 7d7dce3 | 2023-06-09 13:34:22 +0000 | [diff] [blame] | 873 | /// @param value the return value |
dan sinclair | 68a8b09 | 2023-05-26 04:31:50 +0000 | [diff] [blame] | 874 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 875 | template <typename ARG> |
| 876 | ir::Return* Return(ir::Function* func, ARG&& value) { |
James Price | 9e819bf | 2023-06-28 12:13:41 +0000 | [diff] [blame] | 877 | if constexpr (std::is_same_v<std::decay_t<ARG>, ir::Value*>) { |
| 878 | if (value == nullptr) { |
| 879 | return Append(ir.instructions.Create<ir::Return>(func)); |
| 880 | } |
| 881 | } |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 882 | auto* val = Value(std::forward<ARG>(value)); |
| 883 | return Append(ir.instructions.Create<ir::Return>(func, val)); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 884 | } |
dan sinclair | 68a8b09 | 2023-05-26 04:31:50 +0000 | [diff] [blame] | 885 | |
dan sinclair | 0202531 | 2023-05-26 13:14:44 +0000 | [diff] [blame] | 886 | /// Creates a loop next iteration instruction |
| 887 | /// @param loop the loop being iterated |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 888 | /// @param args the arguments for the target MultiInBlock |
dan sinclair | 0202531 | 2023-05-26 13:14:44 +0000 | [diff] [blame] | 889 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 890 | template <typename... ARGS> |
| 891 | ir::NextIteration* NextIteration(ir::Loop* loop, ARGS&&... args) { |
dan sinclair | 2ef2311 | 2023-06-14 10:16:53 +0000 | [diff] [blame] | 892 | return Append( |
dan sinclair | 367fad8 | 2023-06-19 12:58:53 +0000 | [diff] [blame] | 893 | ir.instructions.Create<ir::NextIteration>(loop, Values(std::forward<ARGS>(args)...))); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 894 | } |
dan sinclair | 0202531 | 2023-05-26 13:14:44 +0000 | [diff] [blame] | 895 | |
dan sinclair | e982520 | 2023-05-26 11:33:38 +0000 | [diff] [blame] | 896 | /// Creates a loop break-if instruction |
| 897 | /// @param condition the break condition |
| 898 | /// @param loop the loop being iterated |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 899 | /// @param args the arguments for the target MultiInBlock |
dan sinclair | e982520 | 2023-05-26 11:33:38 +0000 | [diff] [blame] | 900 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 901 | template <typename CONDITION, typename... ARGS> |
Ben Clayton | 3d9c556 | 2023-06-28 23:59:23 +0000 | [diff] [blame] | 902 | ir::BreakIf* BreakIf(ir::Loop* loop, CONDITION&& condition, ARGS&&... args) { |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 903 | CheckForNonDeterministicEvaluation<CONDITION, ARGS...>(); |
| 904 | auto* cond_val = Value(std::forward<CONDITION>(condition)); |
| 905 | return Append(ir.instructions.Create<ir::BreakIf>(cond_val, loop, |
| 906 | Values(std::forward<ARGS>(args)...))); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 907 | } |
dan sinclair | e982520 | 2023-05-26 11:33:38 +0000 | [diff] [blame] | 908 | |
dan sinclair | 4957327 | 2023-05-26 04:33:30 +0000 | [diff] [blame] | 909 | /// Creates a continue instruction |
| 910 | /// @param loop the loop being continued |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 911 | /// @param args the arguments for the target MultiInBlock |
dan sinclair | 4957327 | 2023-05-26 04:33:30 +0000 | [diff] [blame] | 912 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 913 | template <typename... ARGS> |
| 914 | ir::Continue* Continue(ir::Loop* loop, ARGS&&... args) { |
dan sinclair | 367fad8 | 2023-06-19 12:58:53 +0000 | [diff] [blame] | 915 | return Append( |
| 916 | ir.instructions.Create<ir::Continue>(loop, Values(std::forward<ARGS>(args)...))); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 917 | } |
dan sinclair | 4957327 | 2023-05-26 04:33:30 +0000 | [diff] [blame] | 918 | |
dan sinclair | bdbbffb | 2023-05-26 11:42:22 +0000 | [diff] [blame] | 919 | /// Creates an exit switch instruction |
| 920 | /// @param sw the switch being exited |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 921 | /// @param args the arguments for the target MultiInBlock |
dan sinclair | bdbbffb | 2023-05-26 11:42:22 +0000 | [diff] [blame] | 922 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 923 | template <typename... ARGS> |
| 924 | ir::ExitSwitch* ExitSwitch(ir::Switch* sw, ARGS&&... args) { |
dan sinclair | 367fad8 | 2023-06-19 12:58:53 +0000 | [diff] [blame] | 925 | return Append( |
| 926 | ir.instructions.Create<ir::ExitSwitch>(sw, Values(std::forward<ARGS>(args)...))); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 927 | } |
dan sinclair | bdbbffb | 2023-05-26 11:42:22 +0000 | [diff] [blame] | 928 | |
| 929 | /// Creates an exit loop instruction |
| 930 | /// @param loop the loop being exited |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 931 | /// @param args the arguments for the target MultiInBlock |
dan sinclair | bdbbffb | 2023-05-26 11:42:22 +0000 | [diff] [blame] | 932 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 933 | template <typename... ARGS> |
| 934 | ir::ExitLoop* ExitLoop(ir::Loop* loop, ARGS&&... args) { |
dan sinclair | 367fad8 | 2023-06-19 12:58:53 +0000 | [diff] [blame] | 935 | return Append( |
| 936 | ir.instructions.Create<ir::ExitLoop>(loop, Values(std::forward<ARGS>(args)...))); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 937 | } |
dan sinclair | bdbbffb | 2023-05-26 11:42:22 +0000 | [diff] [blame] | 938 | |
| 939 | /// Creates an exit if instruction |
| 940 | /// @param i the if being exited |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 941 | /// @param args the arguments for the target MultiInBlock |
dan sinclair | 68b4e64 | 2023-05-23 22:26:24 +0000 | [diff] [blame] | 942 | /// @returns the instruction |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 943 | template <typename... ARGS> |
| 944 | ir::ExitIf* ExitIf(ir::If* i, ARGS&&... args) { |
dan sinclair | 367fad8 | 2023-06-19 12:58:53 +0000 | [diff] [blame] | 945 | return Append(ir.instructions.Create<ir::ExitIf>(i, Values(std::forward<ARGS>(args)...))); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 946 | } |
dan sinclair | 68b4e64 | 2023-05-23 22:26:24 +0000 | [diff] [blame] | 947 | |
Ben Clayton | a059e59 | 2023-06-19 16:59:00 +0000 | [diff] [blame] | 948 | /// Creates an exit instruction for the given control instruction |
| 949 | /// @param inst the control instruction being exited |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 950 | /// @param args the arguments for the target MultiInBlock |
Ben Clayton | a059e59 | 2023-06-19 16:59:00 +0000 | [diff] [blame] | 951 | /// @returns the exit instruction, or nullptr if the control instruction is not supported. |
| 952 | template <typename... ARGS> |
Ben Clayton | b274678 | 2023-06-21 10:25:50 +0000 | [diff] [blame] | 953 | ir::Exit* Exit(ir::ControlInstruction* inst, ARGS&&... args) { |
Ben Clayton | a059e59 | 2023-06-19 16:59:00 +0000 | [diff] [blame] | 954 | return tint::Switch( |
| 955 | inst, // |
| 956 | [&](ir::If* i) { return ExitIf(i, std::forward<ARGS>(args)...); }, |
| 957 | [&](ir::Loop* i) { return ExitLoop(i, std::forward<ARGS>(args)...); }, |
| 958 | [&](ir::Switch* i) { return ExitSwitch(i, std::forward<ARGS>(args)...); }); |
| 959 | } |
| 960 | |
dan sinclair | 0531610 | 2023-05-17 13:28:47 +0000 | [diff] [blame] | 961 | /// Creates a new `BlockParam` |
| 962 | /// @param type the parameter type |
| 963 | /// @returns the value |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 964 | ir::BlockParam* BlockParam(const core::type::Type* type); |
dan sinclair | 0531610 | 2023-05-17 13:28:47 +0000 | [diff] [blame] | 965 | |
James Price | 0a6f408 | 2023-07-29 00:21:35 +0000 | [diff] [blame] | 966 | /// Creates a new `BlockParam` with a name. |
| 967 | /// @param name the parameter name |
| 968 | /// @param type the parameter type |
| 969 | /// @returns the value |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 970 | ir::BlockParam* BlockParam(std::string_view name, const core::type::Type* type); |
James Price | 0a6f408 | 2023-07-29 00:21:35 +0000 | [diff] [blame] | 971 | |
dan sinclair | 84d750e | 2023-05-18 08:50:34 +0000 | [diff] [blame] | 972 | /// Creates a new `FunctionParam` |
| 973 | /// @param type the parameter type |
| 974 | /// @returns the value |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 975 | ir::FunctionParam* FunctionParam(const core::type::Type* type); |
dan sinclair | 84d750e | 2023-05-18 08:50:34 +0000 | [diff] [blame] | 976 | |
James Price | 25b5146 | 2023-06-28 12:13:41 +0000 | [diff] [blame] | 977 | /// Creates a new `FunctionParam` with a name. |
| 978 | /// @param name the parameter name |
| 979 | /// @param type the parameter type |
| 980 | /// @returns the value |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 981 | ir::FunctionParam* FunctionParam(std::string_view name, const core::type::Type* type); |
James Price | 25b5146 | 2023-06-28 12:13:41 +0000 | [diff] [blame] | 982 | |
dan sinclair | fb4d0ae | 2023-06-02 10:58:22 +0000 | [diff] [blame] | 983 | /// Creates a new `Access` |
| 984 | /// @param type the return type |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 985 | /// @param object the object being accessed |
dan sinclair | fb4d0ae | 2023-06-02 10:58:22 +0000 | [diff] [blame] | 986 | /// @param indices the access indices |
| 987 | /// @returns the instruction |
dan sinclair | 0d80c3d | 2023-06-19 13:32:03 +0000 | [diff] [blame] | 988 | template <typename OBJ, typename... ARGS> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 989 | ir::Access* Access(const core::type::Type* type, OBJ&& object, ARGS&&... indices) { |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 990 | CheckForNonDeterministicEvaluation<OBJ, ARGS...>(); |
| 991 | auto* obj_val = Value(std::forward<OBJ>(object)); |
| 992 | return Append(ir.instructions.Create<ir::Access>(InstructionResult(type), obj_val, |
dan sinclair | 367fad8 | 2023-06-19 12:58:53 +0000 | [diff] [blame] | 993 | Values(std::forward<ARGS>(indices)...))); |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 994 | } |
dan sinclair | fb4d0ae | 2023-06-02 10:58:22 +0000 | [diff] [blame] | 995 | |
dan sinclair | 9c2369a | 2023-06-02 18:33:59 +0000 | [diff] [blame] | 996 | /// Creates a new `Swizzle` |
| 997 | /// @param type the return type |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 998 | /// @param object the object being swizzled |
| 999 | /// @param indices the swizzle indices |
dan sinclair | 9c2369a | 2023-06-02 18:33:59 +0000 | [diff] [blame] | 1000 | /// @returns the instruction |
dan sinclair | 0d80c3d | 2023-06-19 13:32:03 +0000 | [diff] [blame] | 1001 | template <typename OBJ> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 1002 | ir::Swizzle* Swizzle(const core::type::Type* type, OBJ&& object, VectorRef<uint32_t> indices) { |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 1003 | auto* obj_val = Value(std::forward<OBJ>(object)); |
| 1004 | return Append(ir.instructions.Create<ir::Swizzle>(InstructionResult(type), obj_val, |
| 1005 | std::move(indices))); |
dan sinclair | 0d80c3d | 2023-06-19 13:32:03 +0000 | [diff] [blame] | 1006 | } |
Ben Clayton | 039ffdc | 2023-06-09 22:58:09 +0000 | [diff] [blame] | 1007 | |
| 1008 | /// Creates a new `Swizzle` |
| 1009 | /// @param type the return type |
| 1010 | /// @param object the object being swizzled |
| 1011 | /// @param indices the swizzle indices |
| 1012 | /// @returns the instruction |
dan sinclair | 0d80c3d | 2023-06-19 13:32:03 +0000 | [diff] [blame] | 1013 | template <typename OBJ> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 1014 | ir::Swizzle* Swizzle(const core::type::Type* type, |
dan sinclair | 0d80c3d | 2023-06-19 13:32:03 +0000 | [diff] [blame] | 1015 | OBJ&& object, |
| 1016 | std::initializer_list<uint32_t> indices) { |
Ben Clayton | 8232b50 | 2023-06-29 16:10:29 +0000 | [diff] [blame] | 1017 | auto* obj_val = Value(std::forward<OBJ>(object)); |
| 1018 | return Append(ir.instructions.Create<ir::Swizzle>(InstructionResult(type), obj_val, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1019 | Vector<uint32_t, 4>(indices))); |
dan sinclair | 0d80c3d | 2023-06-19 13:32:03 +0000 | [diff] [blame] | 1020 | } |
dan sinclair | 9c2369a | 2023-06-02 18:33:59 +0000 | [diff] [blame] | 1021 | |
James Price | 3adb321 | 2023-07-12 19:05:15 +0000 | [diff] [blame] | 1022 | /// Creates a terminate invocation instruction |
| 1023 | /// @returns the instruction |
| 1024 | ir::TerminateInvocation* TerminateInvocation(); |
| 1025 | |
Ben Clayton | 4915adc | 2023-06-19 21:32:11 +0000 | [diff] [blame] | 1026 | /// Creates an unreachable instruction |
| 1027 | /// @returns the instruction |
| 1028 | ir::Unreachable* Unreachable(); |
| 1029 | |
dan sinclair | 367fad8 | 2023-06-19 12:58:53 +0000 | [diff] [blame] | 1030 | /// Creates a new runtime value |
| 1031 | /// @param type the return type |
| 1032 | /// @returns the value |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 1033 | ir::InstructionResult* InstructionResult(const core::type::Type* type) { |
dan sinclair | 367fad8 | 2023-06-19 12:58:53 +0000 | [diff] [blame] | 1034 | return ir.values.Create<ir::InstructionResult>(type); |
| 1035 | } |
| 1036 | |
James Price | 6f8cb5f | 2023-07-29 13:11:28 +0000 | [diff] [blame] | 1037 | /// Create a ranged loop with a callback to build the loop body. |
| 1038 | /// @param ty the type manager to use for new types |
| 1039 | /// @param start the first loop index |
| 1040 | /// @param end one past the last loop index |
| 1041 | /// @param step the loop index step amount |
| 1042 | /// @param cb the callback to call for the loop body |
| 1043 | template <typename START, typename END, typename STEP, typename FUNCTION> |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 1044 | void LoopRange(core::type::Manager& ty, START&& start, END&& end, STEP&& step, FUNCTION&& cb) { |
James Price | 6f8cb5f | 2023-07-29 13:11:28 +0000 | [diff] [blame] | 1045 | auto* start_value = Value(std::forward<START>(start)); |
| 1046 | auto* end_value = Value(std::forward<END>(end)); |
| 1047 | auto* step_value = Value(std::forward<STEP>(step)); |
| 1048 | |
| 1049 | auto* loop = Loop(); |
| 1050 | auto* idx = BlockParam("idx", start_value->Type()); |
| 1051 | loop->Body()->SetParams({idx}); |
| 1052 | Append(loop->Initializer(), [&] { |
| 1053 | // Start the loop with `idx = start`. |
| 1054 | NextIteration(loop, start_value); |
| 1055 | }); |
| 1056 | Append(loop->Body(), [&] { |
| 1057 | // Loop until `idx == end`. |
| 1058 | auto* breakif = If(GreaterThanEqual(ty.bool_(), idx, end_value)); |
| 1059 | Append(breakif->True(), [&] { // |
| 1060 | ExitLoop(loop); |
| 1061 | }); |
| 1062 | |
| 1063 | cb(idx); |
| 1064 | |
| 1065 | Continue(loop); |
| 1066 | }); |
| 1067 | Append(loop->Continuing(), [&] { |
| 1068 | // Update the index with `idx += step` and go to the next iteration. |
| 1069 | auto* new_idx = Add(idx->Type(), idx, step_value); |
| 1070 | NextIteration(loop, new_idx); |
| 1071 | }); |
| 1072 | } |
| 1073 | |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 1074 | /// The IR module. |
dan sinclair | 809187c | 2023-05-15 23:42:33 +0000 | [diff] [blame] | 1075 | Module& ir; |
Ben Clayton | a8fce7c | 2023-07-12 18:39:00 +0000 | [diff] [blame] | 1076 | |
| 1077 | private: |
| 1078 | /// @returns the element type of the vector-pointer type |
| 1079 | /// Asserts and return i32 if @p type is not a pointer to a vector |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 1080 | const core::type::Type* VectorPtrElementType(const core::type::Type* type); |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 1081 | }; |
| 1082 | |
dan sinclair | 6f138fe | 2023-08-15 21:29:34 +0000 | [diff] [blame] | 1083 | } // namespace tint::core::ir |
dan sinclair | eee8d88 | 2022-10-28 01:22:58 +0000 | [diff] [blame] | 1084 | |
dan sinclair | 97c3727 | 2023-07-24 17:11:53 +0000 | [diff] [blame] | 1085 | #endif // SRC_TINT_LANG_CORE_IR_BUILDER_H_ |