Rename 'intrinsic' to 'builtin'

This matches the term used in the WGSL spec.

Change-Id: I4603332b828450c126ef806f1064ed54f372013f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/78787
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2022-02-02 23:07:11 +00:00
parent a996ffbd1f
commit b85e692aa7
4600 changed files with 6765 additions and 6819 deletions

View File

@ -117,7 +117,7 @@ type nodes.
Semantic information is held by `sem::Node`s which describe the program at Semantic information is held by `sem::Node`s which describe the program at
a higher / more abstract level than the AST. This includes information such as a higher / more abstract level than the AST. This includes information such as
the resolved type of each expression, the resolved overload of an intrinsic the resolved type of each expression, the resolved overload of a builtin
function call, and the module scoped variables used by each function. function call, and the module scoped variables used by each function.
Semantic information is generated by the `Resolver` when the `Program` Semantic information is generated by the `Resolver` when the `Program`

View File

@ -337,6 +337,9 @@ libtint_source_set("libtint_core_all_src") {
"ast/workgroup_attribute.cc", "ast/workgroup_attribute.cc",
"ast/workgroup_attribute.h", "ast/workgroup_attribute.h",
"block_allocator.h", "block_allocator.h",
"builtin_table.cc",
"builtin_table.h",
"builtin_table.inl",
"castable.cc", "castable.cc",
"castable.h", "castable.h",
"clone_context.cc", "clone_context.cc",
@ -359,9 +362,6 @@ libtint_source_set("libtint_core_all_src") {
"inspector/resource_binding.h", "inspector/resource_binding.h",
"inspector/scalar.cc", "inspector/scalar.cc",
"inspector/scalar.h", "inspector/scalar.h",
"intrinsic_table.cc",
"intrinsic_table.h",
"intrinsic_table.inl",
"program.cc", "program.cc",
"program.h", "program.h",
"program_builder.cc", "program_builder.cc",
@ -382,6 +382,8 @@ libtint_source_set("libtint_core_all_src") {
"sem/behavior.h", "sem/behavior.h",
"sem/binding_point.h", "sem/binding_point.h",
"sem/bool_type.h", "sem/bool_type.h",
"sem/builtin.h",
"sem/builtin_type.h",
"sem/call.h", "sem/call.h",
"sem/call_target.h", "sem/call_target.h",
"sem/constant.h", "sem/constant.h",
@ -394,8 +396,6 @@ libtint_source_set("libtint_core_all_src") {
"sem/i32_type.h", "sem/i32_type.h",
"sem/if_statement.h", "sem/if_statement.h",
"sem/info.h", "sem/info.h",
"sem/intrinsic.h",
"sem/intrinsic_type.h",
"sem/loop_statement.h", "sem/loop_statement.h",
"sem/matrix_type.h", "sem/matrix_type.h",
"sem/multisampled_texture_type.h", "sem/multisampled_texture_type.h",
@ -536,6 +536,10 @@ libtint_source_set("libtint_sem_src") {
"sem/block_statement.cc", "sem/block_statement.cc",
"sem/bool_type.cc", "sem/bool_type.cc",
"sem/bool_type.h", "sem/bool_type.h",
"sem/builtin.cc",
"sem/builtin.h",
"sem/builtin_type.cc",
"sem/builtin_type.h",
"sem/call.cc", "sem/call.cc",
"sem/call.h", "sem/call.h",
"sem/call_target.cc", "sem/call_target.cc",
@ -561,10 +565,6 @@ libtint_source_set("libtint_sem_src") {
"sem/if_statement.h", "sem/if_statement.h",
"sem/info.cc", "sem/info.cc",
"sem/info.h", "sem/info.h",
"sem/intrinsic.cc",
"sem/intrinsic.h",
"sem/intrinsic_type.cc",
"sem/intrinsic_type.h",
"sem/loop_statement.cc", "sem/loop_statement.cc",
"sem/loop_statement.h", "sem/loop_statement.h",
"sem/matrix_type.cc", "sem/matrix_type.cc",

View File

@ -219,6 +219,9 @@ set(TINT_LIB_SRCS
ast/workgroup_attribute.cc ast/workgroup_attribute.cc
ast/workgroup_attribute.h ast/workgroup_attribute.h
block_allocator.h block_allocator.h
builtin_table.cc
builtin_table.h
builtin_table.inl
castable.cc castable.cc
castable.h castable.h
clone_context.cc clone_context.cc
@ -233,9 +236,6 @@ set(TINT_LIB_SRCS
inspector/resource_binding.h inspector/resource_binding.h
inspector/scalar.cc inspector/scalar.cc
inspector/scalar.h inspector/scalar.h
intrinsic_table.cc
intrinsic_table.h
intrinsic_table.inl
program_builder.cc program_builder.cc
program_builder.h program_builder.h
program_id.cc program_id.cc
@ -260,6 +260,10 @@ set(TINT_LIB_SRCS
sem/binding_point.h sem/binding_point.h
sem/block_statement.cc sem/block_statement.cc
sem/block_statement.h sem/block_statement.h
sem/builtin_type.cc
sem/builtin_type.h
sem/builtin.cc
sem/builtin.h
sem/call_target.cc sem/call_target.cc
sem/call_target.h sem/call_target.h
sem/call.cc sem/call.cc
@ -273,10 +277,6 @@ set(TINT_LIB_SRCS
sem/function.cc sem/function.cc
sem/info.cc sem/info.cc
sem/info.h sem/info.h
sem/intrinsic_type.cc
sem/intrinsic_type.h
sem/intrinsic.cc
sem/intrinsic.h
sem/member_accessor_expression.cc sem/member_accessor_expression.cc
sem/parameter_usage.cc sem/parameter_usage.cc
sem/parameter_usage.h sem/parameter_usage.h
@ -624,6 +624,8 @@ if(TINT_BUILD_TESTS)
ast/bool_test.cc ast/bool_test.cc
ast/break_statement_test.cc ast/break_statement_test.cc
ast/builtin_attribute_test.cc ast/builtin_attribute_test.cc
ast/builtin_texture_helper_test.cc
ast/builtin_texture_helper_test.h
ast/call_expression_test.cc ast/call_expression_test.cc
ast/call_statement_test.cc ast/call_statement_test.cc
ast/case_statement_test.cc ast/case_statement_test.cc
@ -645,8 +647,6 @@ if(TINT_BUILD_TESTS)
ast/index_accessor_expression_test.cc ast/index_accessor_expression_test.cc
ast/int_literal_expression_test.cc ast/int_literal_expression_test.cc
ast/interpolate_attribute_test.cc ast/interpolate_attribute_test.cc
ast/intrinsic_texture_helper_test.cc
ast/intrinsic_texture_helper_test.h
ast/invariant_attribute_test.cc ast/invariant_attribute_test.cc
ast/location_attribute_test.cc ast/location_attribute_test.cc
ast/loop_statement_test.cc ast/loop_statement_test.cc
@ -682,6 +682,7 @@ if(TINT_BUILD_TESTS)
ast/vector_test.cc ast/vector_test.cc
ast/workgroup_attribute_test.cc ast/workgroup_attribute_test.cc
block_allocator_test.cc block_allocator_test.cc
builtin_table_test.cc
castable_test.cc castable_test.cc
clone_context_test.cc clone_context_test.cc
debug_test.cc debug_test.cc
@ -689,7 +690,6 @@ if(TINT_BUILD_TESTS)
diagnostic/diagnostic_test.cc diagnostic/diagnostic_test.cc
diagnostic/formatter_test.cc diagnostic/formatter_test.cc
diagnostic/printer_test.cc diagnostic/printer_test.cc
intrinsic_table_test.cc
program_test.cc program_test.cc
resolver/array_accessor_test.cc resolver/array_accessor_test.cc
resolver/assignment_validation_test.cc resolver/assignment_validation_test.cc
@ -697,6 +697,8 @@ if(TINT_BUILD_TESTS)
resolver/atomics_validation_test.cc resolver/atomics_validation_test.cc
resolver/bitcast_validation_test.cc resolver/bitcast_validation_test.cc
resolver/builtins_validation_test.cc resolver/builtins_validation_test.cc
resolver/builtin_test.cc
resolver/builtin_validation_test.cc
resolver/call_test.cc resolver/call_test.cc
resolver/call_validation_test.cc resolver/call_validation_test.cc
resolver/compound_statement_test.cc resolver/compound_statement_test.cc
@ -707,8 +709,6 @@ if(TINT_BUILD_TESTS)
resolver/function_validation_test.cc resolver/function_validation_test.cc
resolver/host_shareable_validation_test.cc resolver/host_shareable_validation_test.cc
resolver/inferred_type_test.cc resolver/inferred_type_test.cc
resolver/intrinsic_test.cc
resolver/intrinsic_validation_test.cc
resolver/is_host_shareable_test.cc resolver/is_host_shareable_test.cc
resolver/is_storeable_test.cc resolver/is_storeable_test.cc
resolver/pipeline_overridable_constant_test.cc resolver/pipeline_overridable_constant_test.cc
@ -732,12 +732,12 @@ if(TINT_BUILD_TESTS)
scope_stack_test.cc scope_stack_test.cc
sem/atomic_type_test.cc sem/atomic_type_test.cc
sem/bool_type_test.cc sem/bool_type_test.cc
sem/builtin_test.cc
sem/depth_multisampled_texture_type_test.cc sem/depth_multisampled_texture_type_test.cc
sem/depth_texture_type_test.cc sem/depth_texture_type_test.cc
sem/external_texture_type_test.cc sem/external_texture_type_test.cc
sem/f32_type_test.cc sem/f32_type_test.cc
sem/i32_type_test.cc sem/i32_type_test.cc
sem/intrinsic_test.cc
sem/matrix_type_test.cc sem/matrix_type_test.cc
sem/multisampled_texture_type_test.cc sem/multisampled_texture_type_test.cc
sem/pointer_type_test.cc sem/pointer_type_test.cc
@ -911,6 +911,8 @@ if(TINT_BUILD_TESTS)
writer/spirv/builder_binary_expression_test.cc writer/spirv/builder_binary_expression_test.cc
writer/spirv/builder_bitcast_expression_test.cc writer/spirv/builder_bitcast_expression_test.cc
writer/spirv/builder_block_test.cc writer/spirv/builder_block_test.cc
writer/spirv/builder_builtin_test.cc
writer/spirv/builder_builtin_texture_test.cc
writer/spirv/builder_call_test.cc writer/spirv/builder_call_test.cc
writer/spirv/builder_constructor_expression_test.cc writer/spirv/builder_constructor_expression_test.cc
writer/spirv/builder_discard_test.cc writer/spirv/builder_discard_test.cc
@ -922,8 +924,6 @@ if(TINT_BUILD_TESTS)
writer/spirv/builder_global_variable_test.cc writer/spirv/builder_global_variable_test.cc
writer/spirv/builder_ident_expression_test.cc writer/spirv/builder_ident_expression_test.cc
writer/spirv/builder_if_test.cc writer/spirv/builder_if_test.cc
writer/spirv/builder_intrinsic_test.cc
writer/spirv/builder_intrinsic_texture_test.cc
writer/spirv/builder_literal_test.cc writer/spirv/builder_literal_test.cc
writer/spirv/builder_loop_test.cc writer/spirv/builder_loop_test.cc
writer/spirv/builder_return_test.cc writer/spirv/builder_return_test.cc
@ -1020,6 +1020,8 @@ if(TINT_BUILD_TESTS)
writer/msl/generator_impl_bitcast_test.cc writer/msl/generator_impl_bitcast_test.cc
writer/msl/generator_impl_block_test.cc writer/msl/generator_impl_block_test.cc
writer/msl/generator_impl_break_test.cc writer/msl/generator_impl_break_test.cc
writer/msl/generator_impl_builtin_test.cc
writer/msl/generator_impl_builtin_texture_test.cc
writer/msl/generator_impl_call_test.cc writer/msl/generator_impl_call_test.cc
writer/msl/generator_impl_case_test.cc writer/msl/generator_impl_case_test.cc
writer/msl/generator_impl_cast_test.cc writer/msl/generator_impl_cast_test.cc
@ -1030,8 +1032,6 @@ if(TINT_BUILD_TESTS)
writer/msl/generator_impl_identifier_test.cc writer/msl/generator_impl_identifier_test.cc
writer/msl/generator_impl_if_test.cc writer/msl/generator_impl_if_test.cc
writer/msl/generator_impl_import_test.cc writer/msl/generator_impl_import_test.cc
writer/msl/generator_impl_intrinsic_test.cc
writer/msl/generator_impl_intrinsic_texture_test.cc
writer/msl/generator_impl_loop_test.cc writer/msl/generator_impl_loop_test.cc
writer/msl/generator_impl_member_accessor_test.cc writer/msl/generator_impl_member_accessor_test.cc
writer/msl/generator_impl_module_constant_test.cc writer/msl/generator_impl_module_constant_test.cc
@ -1054,6 +1054,8 @@ if(TINT_BUILD_TESTS)
writer/glsl/generator_impl_bitcast_test.cc writer/glsl/generator_impl_bitcast_test.cc
writer/glsl/generator_impl_block_test.cc writer/glsl/generator_impl_block_test.cc
writer/glsl/generator_impl_break_test.cc writer/glsl/generator_impl_break_test.cc
writer/glsl/generator_impl_builtin_test.cc
writer/glsl/generator_impl_builtin_texture_test.cc
writer/glsl/generator_impl_call_test.cc writer/glsl/generator_impl_call_test.cc
writer/glsl/generator_impl_case_test.cc writer/glsl/generator_impl_case_test.cc
writer/glsl/generator_impl_cast_test.cc writer/glsl/generator_impl_cast_test.cc
@ -1063,8 +1065,6 @@ if(TINT_BUILD_TESTS)
writer/glsl/generator_impl_function_test.cc writer/glsl/generator_impl_function_test.cc
writer/glsl/generator_impl_identifier_test.cc writer/glsl/generator_impl_identifier_test.cc
writer/glsl/generator_impl_if_test.cc writer/glsl/generator_impl_if_test.cc
writer/glsl/generator_impl_intrinsic_test.cc
writer/glsl/generator_impl_intrinsic_texture_test.cc
writer/glsl/generator_impl_import_test.cc writer/glsl/generator_impl_import_test.cc
writer/glsl/generator_impl_loop_test.cc writer/glsl/generator_impl_loop_test.cc
writer/glsl/generator_impl_member_accessor_test.cc writer/glsl/generator_impl_member_accessor_test.cc
@ -1089,6 +1089,8 @@ if(TINT_BUILD_TESTS)
writer/hlsl/generator_impl_bitcast_test.cc writer/hlsl/generator_impl_bitcast_test.cc
writer/hlsl/generator_impl_block_test.cc writer/hlsl/generator_impl_block_test.cc
writer/hlsl/generator_impl_break_test.cc writer/hlsl/generator_impl_break_test.cc
writer/hlsl/generator_impl_builtin_test.cc
writer/hlsl/generator_impl_builtin_texture_test.cc
writer/hlsl/generator_impl_call_test.cc writer/hlsl/generator_impl_call_test.cc
writer/hlsl/generator_impl_case_test.cc writer/hlsl/generator_impl_case_test.cc
writer/hlsl/generator_impl_cast_test.cc writer/hlsl/generator_impl_cast_test.cc
@ -1098,8 +1100,6 @@ if(TINT_BUILD_TESTS)
writer/hlsl/generator_impl_function_test.cc writer/hlsl/generator_impl_function_test.cc
writer/hlsl/generator_impl_identifier_test.cc writer/hlsl/generator_impl_identifier_test.cc
writer/hlsl/generator_impl_if_test.cc writer/hlsl/generator_impl_if_test.cc
writer/hlsl/generator_impl_intrinsic_test.cc
writer/hlsl/generator_impl_intrinsic_texture_test.cc
writer/hlsl/generator_impl_import_test.cc writer/hlsl/generator_impl_import_test.cc
writer/hlsl/generator_impl_loop_test.cc writer/hlsl/generator_impl_loop_test.cc
writer/hlsl/generator_impl_member_accessor_test.cc writer/hlsl/generator_impl_member_accessor_test.cc

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/intrinsic_texture_helper_test.h" #include "src/ast/builtin_texture_helper_test.h"
#include "src/sem/depth_texture_type.h" #include "src/sem/depth_texture_type.h"
#include "src/sem/multisampled_texture_type.h" #include "src/sem/multisampled_texture_type.h"
@ -20,7 +20,7 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
namespace intrinsic { namespace builtin {
namespace test { namespace test {
using u32 = ProgramBuilder::u32; using u32 = ProgramBuilder::u32;
@ -137,11 +137,11 @@ std::ostream& operator<<(std::ostream& out, const TextureOverloadCase& data) {
const ast::Type* TextureOverloadCase::BuildResultVectorComponentType( const ast::Type* TextureOverloadCase::BuildResultVectorComponentType(
ProgramBuilder* b) const { ProgramBuilder* b) const {
switch (texture_data_type) { switch (texture_data_type) {
case ast::intrinsic::test::TextureDataType::kF32: case ast::builtin::test::TextureDataType::kF32:
return b->ty.f32(); return b->ty.f32();
case ast::intrinsic::test::TextureDataType::kU32: case ast::builtin::test::TextureDataType::kU32:
return b->ty.u32(); return b->ty.u32();
case ast::intrinsic::test::TextureDataType::kI32: case ast::builtin::test::TextureDataType::kI32:
return b->ty.i32(); return b->ty.i32();
} }
@ -156,29 +156,29 @@ const ast::Variable* TextureOverloadCase::BuildTextureVariable(
b->create<ast::BindingAttribute>(0), b->create<ast::BindingAttribute>(0),
}; };
switch (texture_kind) { switch (texture_kind) {
case ast::intrinsic::test::TextureKind::kRegular: case ast::builtin::test::TextureKind::kRegular:
return b->Global("texture", return b->Global("texture",
b->ty.sampled_texture(texture_dimension, b->ty.sampled_texture(texture_dimension,
BuildResultVectorComponentType(b)), BuildResultVectorComponentType(b)),
attrs); attrs);
case ast::intrinsic::test::TextureKind::kDepth: case ast::builtin::test::TextureKind::kDepth:
return b->Global("texture", b->ty.depth_texture(texture_dimension), return b->Global("texture", b->ty.depth_texture(texture_dimension),
attrs); attrs);
case ast::intrinsic::test::TextureKind::kDepthMultisampled: case ast::builtin::test::TextureKind::kDepthMultisampled:
return b->Global("texture", return b->Global("texture",
b->ty.depth_multisampled_texture(texture_dimension), b->ty.depth_multisampled_texture(texture_dimension),
attrs); attrs);
case ast::intrinsic::test::TextureKind::kMultisampled: case ast::builtin::test::TextureKind::kMultisampled:
return b->Global( return b->Global(
"texture", "texture",
b->ty.multisampled_texture(texture_dimension, b->ty.multisampled_texture(texture_dimension,
BuildResultVectorComponentType(b)), BuildResultVectorComponentType(b)),
attrs); attrs);
case ast::intrinsic::test::TextureKind::kStorage: { case ast::builtin::test::TextureKind::kStorage: {
auto* st = b->ty.storage_texture(texture_dimension, texel_format, access); auto* st = b->ty.storage_texture(texture_dimension, texel_format, access);
return b->Global("texture", st, attrs); return b->Global("texture", st, attrs);
} }
@ -2281,6 +2281,6 @@ bool ReturnsVoid(ValidTextureOverload texture_overload) {
} }
} // namespace test } // namespace test
} // namespace intrinsic } // namespace builtin
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint

View File

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef SRC_AST_INTRINSIC_TEXTURE_HELPER_TEST_H_ #ifndef SRC_AST_BUILTIN_TEXTURE_HELPER_TEST_H_
#define SRC_AST_INTRINSIC_TEXTURE_HELPER_TEST_H_ #define SRC_AST_BUILTIN_TEXTURE_HELPER_TEST_H_
#include <vector> #include <vector>
@ -23,7 +23,7 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
namespace intrinsic { namespace builtin {
namespace test { namespace test {
enum class TextureKind { enum class TextureKind {
@ -181,10 +181,10 @@ enum class ValidTextureOverload {
}; };
/// @param texture_overload the ValidTextureOverload /// @param texture_overload the ValidTextureOverload
/// @returns true if the ValidTextureOverload intrinsic returns no value. /// @returns true if the ValidTextureOverload builtin returns no value.
bool ReturnsVoid(ValidTextureOverload texture_overload); bool ReturnsVoid(ValidTextureOverload texture_overload);
/// Describes a texture intrinsic overload /// Describes a texture builtin overload
struct TextureOverloadCase { struct TextureOverloadCase {
/// Constructor for textureSample...() functions /// Constructor for textureSample...() functions
TextureOverloadCase(ValidTextureOverload, TextureOverloadCase(ValidTextureOverload,
@ -262,8 +262,8 @@ struct TextureOverloadCase {
std::ostream& operator<<(std::ostream& out, const TextureOverloadCase& data); std::ostream& operator<<(std::ostream& out, const TextureOverloadCase& data);
} // namespace test } // namespace test
} // namespace intrinsic } // namespace builtin
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint
#endif // SRC_AST_INTRINSIC_TEXTURE_HELPER_TEST_H_ #endif // SRC_AST_BUILTIN_TEXTURE_HELPER_TEST_H_

View File

@ -26,7 +26,7 @@ class IdentifierExpression;
/// A call expression - represents either a: /// A call expression - represents either a:
/// * sem::Function /// * sem::Function
/// * sem::Intrinsic /// * sem::Builtin
/// * sem::TypeConstructor /// * sem::TypeConstructor
/// * sem::TypeConversion /// * sem::TypeConversion
class CallExpression : public Castable<CallExpression, Expression> { class CallExpression : public Castable<CallExpression, Expression> {
@ -64,7 +64,7 @@ class CallExpression : public Castable<CallExpression, Expression> {
/// Target is either an identifier, or a Type. /// Target is either an identifier, or a Type.
/// One of these must be nullptr and the other a non-nullptr. /// One of these must be nullptr and the other a non-nullptr.
struct Target { struct Target {
/// name is a function or intrinsic to call, or type name to construct or /// name is a function or builtin to call, or type name to construct or
/// cast-to /// cast-to
const IdentifierExpression* name = nullptr; const IdentifierExpression* name = nullptr;
/// type to construct or cast-to /// type to construct or cast-to

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/intrinsic_table.h" #include "src/builtin_table.h"
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
@ -286,7 +286,7 @@ class OpenNumberMatcher : public NumberMatcher {
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Binding functions for use in the generated intrinsic_table.inl // Binding functions for use in the generated builtin_table.inl
// TODO(bclayton): See if we can move more of this hand-rolled code to the // TODO(bclayton): See if we can move more of this hand-rolled code to the
// template // template
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -793,19 +793,19 @@ struct OverloadInfo {
bool is_deprecated; bool is_deprecated;
}; };
/// IntrinsicInfo describes an intrinsic function /// BuiltinInfo describes a builtin function
struct IntrinsicInfo { struct BuiltinInfo {
/// Number of overloads of the intrinsic function /// Number of overloads of the builtin function
const uint8_t num_overloads; const uint8_t num_overloads;
/// Pointer to the start of the overloads for the function /// Pointer to the start of the overloads for the function
OverloadInfo const* const overloads; OverloadInfo const* const overloads;
}; };
#include "intrinsic_table.inl" #include "builtin_table.inl"
/// IntrinsicPrototype describes a fully matched intrinsic function, which is /// BuiltinPrototype describes a fully matched builtin function, which is
/// used as a lookup for building unique sem::Intrinsic instances. /// used as a lookup for building unique sem::Builtin instances.
struct IntrinsicPrototype { struct BuiltinPrototype {
/// Parameter describes a single parameter /// Parameter describes a single parameter
struct Parameter { struct Parameter {
/// Parameter type /// Parameter type
@ -814,11 +814,11 @@ struct IntrinsicPrototype {
ParameterUsage const usage = ParameterUsage::kNone; ParameterUsage const usage = ParameterUsage::kNone;
}; };
/// Hasher provides a hash function for the IntrinsicPrototype /// Hasher provides a hash function for the BuiltinPrototype
struct Hasher { struct Hasher {
/// @param i the IntrinsicPrototype to create a hash for /// @param i the BuiltinPrototype to create a hash for
/// @return the hash value /// @return the hash value
inline std::size_t operator()(const IntrinsicPrototype& i) const { inline std::size_t operator()(const BuiltinPrototype& i) const {
size_t hash = utils::Hash(i.parameters.size()); size_t hash = utils::Hash(i.parameters.size());
for (auto& p : i.parameters) { for (auto& p : i.parameters) {
utils::HashCombine(&hash, p.type, p.usage); utils::HashCombine(&hash, p.type, p.usage);
@ -828,15 +828,15 @@ struct IntrinsicPrototype {
} }
}; };
sem::IntrinsicType type = sem::IntrinsicType::kNone; sem::BuiltinType type = sem::BuiltinType::kNone;
std::vector<Parameter> parameters; std::vector<Parameter> parameters;
sem::Type const* return_type = nullptr; sem::Type const* return_type = nullptr;
PipelineStageSet supported_stages; PipelineStageSet supported_stages;
bool is_deprecated = false; bool is_deprecated = false;
}; };
/// Equality operator for IntrinsicPrototype /// Equality operator for BuiltinPrototype
bool operator==(const IntrinsicPrototype& a, const IntrinsicPrototype& b) { bool operator==(const BuiltinPrototype& a, const BuiltinPrototype& b) {
if (a.type != b.type || a.supported_stages != b.supported_stages || if (a.type != b.type || a.supported_stages != b.supported_stages ||
a.return_type != b.return_type || a.is_deprecated != b.is_deprecated || a.return_type != b.return_type || a.is_deprecated != b.is_deprecated ||
a.parameters.size() != b.parameters.size()) { a.parameters.size() != b.parameters.size()) {
@ -852,20 +852,20 @@ bool operator==(const IntrinsicPrototype& a, const IntrinsicPrototype& b) {
return true; return true;
} }
/// Impl is the private implementation of the IntrinsicTable interface. /// Impl is the private implementation of the BuiltinTable interface.
class Impl : public IntrinsicTable { class Impl : public BuiltinTable {
public: public:
explicit Impl(ProgramBuilder& builder); explicit Impl(ProgramBuilder& builder);
const sem::Intrinsic* Lookup(sem::IntrinsicType intrinsic_type, const sem::Builtin* Lookup(sem::BuiltinType builtin_type,
const std::vector<const sem::Type*>& args, const std::vector<const sem::Type*>& args,
const Source& source) override; const Source& source) override;
private: private:
const sem::Intrinsic* Match(sem::IntrinsicType intrinsic_type, const sem::Builtin* Match(sem::BuiltinType builtin_type,
const OverloadInfo& overload, const OverloadInfo& overload,
const std::vector<const sem::Type*>& args, const std::vector<const sem::Type*>& args,
int& match_score); int& match_score);
MatchState Match(ClosedState& closed, MatchState Match(ClosedState& closed,
const OverloadInfo& overload, const OverloadInfo& overload,
@ -873,23 +873,21 @@ class Impl : public IntrinsicTable {
void PrintOverload(std::ostream& ss, void PrintOverload(std::ostream& ss,
const OverloadInfo& overload, const OverloadInfo& overload,
sem::IntrinsicType intrinsic_type) const; sem::BuiltinType builtin_type) const;
ProgramBuilder& builder; ProgramBuilder& builder;
Matchers matchers; Matchers matchers;
std::unordered_map<IntrinsicPrototype, std::unordered_map<BuiltinPrototype, sem::Builtin*, BuiltinPrototype::Hasher>
sem::Intrinsic*, builtins;
IntrinsicPrototype::Hasher>
intrinsics;
}; };
/// @return a string representing a call to an intrinsic with the given argument /// @return a string representing a call to a builtin with the given argument
/// types. /// types.
std::string CallSignature(ProgramBuilder& builder, std::string CallSignature(ProgramBuilder& builder,
sem::IntrinsicType intrinsic_type, sem::BuiltinType builtin_type,
const std::vector<const sem::Type*>& args) { const std::vector<const sem::Type*>& args) {
std::stringstream ss; std::stringstream ss;
ss << sem::str(intrinsic_type) << "("; ss << sem::str(builtin_type) << "(";
{ {
bool first = true; bool first = true;
for (auto* arg : args) { for (auto* arg : args) {
@ -915,9 +913,9 @@ std::string OpenNumberMatcher::String(MatchState& state) const {
Impl::Impl(ProgramBuilder& b) : builder(b) {} Impl::Impl(ProgramBuilder& b) : builder(b) {}
const sem::Intrinsic* Impl::Lookup(sem::IntrinsicType intrinsic_type, const sem::Builtin* Impl::Lookup(sem::BuiltinType builtin_type,
const std::vector<const sem::Type*>& args, const std::vector<const sem::Type*>& args,
const Source& source) { const Source& source) {
// Candidate holds information about a mismatched overload that could be what // Candidate holds information about a mismatched overload that could be what
// the user intended to call. // the user intended to call.
struct Candidate { struct Candidate {
@ -928,11 +926,11 @@ const sem::Intrinsic* Impl::Lookup(sem::IntrinsicType intrinsic_type,
// The list of failed matches that had promise. // The list of failed matches that had promise.
std::vector<Candidate> candidates; std::vector<Candidate> candidates;
auto& intrinsic = kIntrinsics[static_cast<uint32_t>(intrinsic_type)]; auto& builtin = kBuiltins[static_cast<uint32_t>(builtin_type)];
for (uint32_t o = 0; o < intrinsic.num_overloads; o++) { for (uint32_t o = 0; o < builtin.num_overloads; o++) {
int match_score = 1000; int match_score = 1000;
auto& overload = intrinsic.overloads[o]; auto& overload = builtin.overloads[o];
if (auto* match = Match(intrinsic_type, overload, args, match_score)) { if (auto* match = Match(builtin_type, overload, args, match_score)) {
return match; return match;
} }
if (match_score > 0) { if (match_score > 0) {
@ -947,7 +945,7 @@ const sem::Intrinsic* Impl::Lookup(sem::IntrinsicType intrinsic_type,
// Generate an error message // Generate an error message
std::stringstream ss; std::stringstream ss;
ss << "no matching call to " << CallSignature(builder, intrinsic_type, args) ss << "no matching call to " << CallSignature(builder, builtin_type, args)
<< std::endl; << std::endl;
if (!candidates.empty()) { if (!candidates.empty()) {
ss << std::endl; ss << std::endl;
@ -955,7 +953,7 @@ const sem::Intrinsic* Impl::Lookup(sem::IntrinsicType intrinsic_type,
<< (candidates.size() > 1 ? "s:" : ":") << std::endl; << (candidates.size() > 1 ? "s:" : ":") << std::endl;
for (auto& candidate : candidates) { for (auto& candidate : candidates) {
ss << " "; ss << " ";
PrintOverload(ss, *candidate.overload, intrinsic_type); PrintOverload(ss, *candidate.overload, builtin_type);
ss << std::endl; ss << std::endl;
} }
} }
@ -963,10 +961,10 @@ const sem::Intrinsic* Impl::Lookup(sem::IntrinsicType intrinsic_type,
return nullptr; return nullptr;
} }
const sem::Intrinsic* Impl::Match(sem::IntrinsicType intrinsic_type, const sem::Builtin* Impl::Match(sem::BuiltinType builtin_type,
const OverloadInfo& overload, const OverloadInfo& overload,
const std::vector<const sem::Type*>& args, const std::vector<const sem::Type*>& args,
int& match_score) { int& match_score) {
// Score wait for argument <-> parameter count matches / mismatches // Score wait for argument <-> parameter count matches / mismatches
constexpr int kScorePerParamArgMismatch = -1; constexpr int kScorePerParamArgMismatch = -1;
constexpr int kScorePerMatchedParam = 2; constexpr int kScorePerMatchedParam = 2;
@ -987,7 +985,7 @@ const sem::Intrinsic* Impl::Match(sem::IntrinsicType intrinsic_type,
ClosedState closed(builder); ClosedState closed(builder);
std::vector<IntrinsicPrototype::Parameter> parameters; std::vector<BuiltinPrototype::Parameter> parameters;
auto num_params = std::min(num_parameters, num_arguments); auto num_params = std::min(num_parameters, num_arguments);
for (uint32_t p = 0; p < num_params; p++) { for (uint32_t p = 0; p < num_params; p++) {
@ -996,7 +994,7 @@ const sem::Intrinsic* Impl::Match(sem::IntrinsicType intrinsic_type,
auto* type = Match(closed, overload, indices).Type(args[p]->UnwrapRef()); auto* type = Match(closed, overload, indices).Type(args[p]->UnwrapRef());
if (type) { if (type) {
parameters.emplace_back( parameters.emplace_back(
IntrinsicPrototype::Parameter{type, parameter.usage}); BuiltinPrototype::Parameter{type, parameter.usage});
match_score += kScorePerMatchedParam; match_score += kScorePerMatchedParam;
} else { } else {
overload_matched = false; overload_matched = false;
@ -1044,7 +1042,7 @@ const sem::Intrinsic* Impl::Match(sem::IntrinsicType intrinsic_type,
return_type = Match(closed, overload, indices).Type(&any); return_type = Match(closed, overload, indices).Type(&any);
if (!return_type) { if (!return_type) {
std::stringstream ss; std::stringstream ss;
PrintOverload(ss, overload, intrinsic_type); PrintOverload(ss, overload, builtin_type);
TINT_ICE(Resolver, builder.Diagnostics()) TINT_ICE(Resolver, builder.Diagnostics())
<< "MatchState.Match() returned null for " << ss.str(); << "MatchState.Match() returned null for " << ss.str();
return nullptr; return nullptr;
@ -1053,25 +1051,25 @@ const sem::Intrinsic* Impl::Match(sem::IntrinsicType intrinsic_type,
return_type = builder.create<sem::Void>(); return_type = builder.create<sem::Void>();
} }
IntrinsicPrototype intrinsic; BuiltinPrototype builtin;
intrinsic.type = intrinsic_type; builtin.type = builtin_type;
intrinsic.return_type = return_type; builtin.return_type = return_type;
intrinsic.parameters = std::move(parameters); builtin.parameters = std::move(parameters);
intrinsic.supported_stages = overload.supported_stages; builtin.supported_stages = overload.supported_stages;
intrinsic.is_deprecated = overload.is_deprecated; builtin.is_deprecated = overload.is_deprecated;
// De-duplicate intrinsics that are identical. // De-duplicate builtins that are identical.
return utils::GetOrCreate(intrinsics, intrinsic, [&] { return utils::GetOrCreate(builtins, builtin, [&] {
std::vector<sem::Parameter*> params; std::vector<sem::Parameter*> params;
params.reserve(intrinsic.parameters.size()); params.reserve(builtin.parameters.size());
for (auto& p : intrinsic.parameters) { for (auto& p : builtin.parameters) {
params.emplace_back(builder.create<sem::Parameter>( params.emplace_back(builder.create<sem::Parameter>(
nullptr, static_cast<uint32_t>(params.size()), p.type, nullptr, static_cast<uint32_t>(params.size()), p.type,
ast::StorageClass::kNone, ast::Access::kUndefined, p.usage)); ast::StorageClass::kNone, ast::Access::kUndefined, p.usage));
} }
return builder.create<sem::Intrinsic>( return builder.create<sem::Builtin>(
intrinsic.type, intrinsic.return_type, std::move(params), builtin.type, builtin.return_type, std::move(params),
intrinsic.supported_stages, intrinsic.is_deprecated); builtin.supported_stages, builtin.is_deprecated);
}); });
} }
@ -1083,10 +1081,10 @@ MatchState Impl::Match(ClosedState& closed,
void Impl::PrintOverload(std::ostream& ss, void Impl::PrintOverload(std::ostream& ss,
const OverloadInfo& overload, const OverloadInfo& overload,
sem::IntrinsicType intrinsic_type) const { sem::BuiltinType builtin_type) const {
ClosedState closed(builder); ClosedState closed(builder);
ss << intrinsic_type << "("; ss << builtin_type << "(";
for (uint32_t p = 0; p < overload.num_parameters; p++) { for (uint32_t p = 0; p < overload.num_parameters; p++) {
auto& parameter = overload.parameters[p]; auto& parameter = overload.parameters[p];
if (p > 0) { if (p > 0) {
@ -1156,12 +1154,11 @@ std::string MatchState::NumName() {
} // namespace } // namespace
std::unique_ptr<IntrinsicTable> IntrinsicTable::Create( std::unique_ptr<BuiltinTable> BuiltinTable::Create(ProgramBuilder& builder) {
ProgramBuilder& builder) {
return std::make_unique<Impl>(builder); return std::make_unique<Impl>(builder);
} }
IntrinsicTable::~IntrinsicTable() = default; BuiltinTable::~BuiltinTable() = default;
/// TypeInfo for the Any type declared in the anonymous namespace above /// TypeInfo for the Any type declared in the anonymous namespace above
TINT_INSTANTIATE_TYPEINFO(Any); TINT_INSTANTIATE_TYPEINFO(Any);

52
src/builtin_table.h Normal file
View File

@ -0,0 +1,52 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_BUILTIN_TABLE_H_
#define SRC_BUILTIN_TABLE_H_
#include <memory>
#include <string>
#include <vector>
#include "src/sem/builtin.h"
namespace tint {
// Forward declarations
class ProgramBuilder;
/// BuiltinTable is a lookup table of all the WGSL builtin functions
class BuiltinTable {
public:
/// @param builder the program builder
/// @return a pointer to a newly created BuiltinTable
static std::unique_ptr<BuiltinTable> Create(ProgramBuilder& builder);
/// Destructor
virtual ~BuiltinTable();
/// Lookup looks for the builtin overload with the given signature, raising
/// an error diagnostic if the builtin was not found.
/// @param type the builtin type
/// @param args the argument types passed to the builtin function
/// @param source the source of the builtin call
/// @return the semantic builtin if found, otherwise nullptr
virtual const sem::Builtin* Lookup(sem::BuiltinType type,
const std::vector<const sem::Type*>& args,
const Source& source) = 0;
};
} // namespace tint
#endif // SRC_BUILTIN_TABLE_H_

View File

@ -13,11 +13,11 @@
// limitations under the License. // limitations under the License.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen // File generated by tools/builtin-gen
// using the template: // using the template:
// src/intrinsic_table.inl.tmpl // src/builtin_table.inl.tmpl
// and the intrinsic defintion file: // and the builtin defintion file:
// src/intrinsics.def // src/builtins.def
// //
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -25,7 +25,7 @@
// clang-format off // clang-format off
/// TypeMatcher for 'type bool' /// TypeMatcher for 'type bool'
/// @see src/intrinsics.def:68:6 /// @see src/builtins.def:68:6
class Bool : public TypeMatcher { class Bool : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -52,7 +52,7 @@ std::string Bool::String(MatchState&) const {
} }
/// TypeMatcher for 'type f32' /// TypeMatcher for 'type f32'
/// @see src/intrinsics.def:69:6 /// @see src/builtins.def:69:6
class F32 : public TypeMatcher { class F32 : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -79,7 +79,7 @@ std::string F32::String(MatchState&) const {
} }
/// TypeMatcher for 'type i32' /// TypeMatcher for 'type i32'
/// @see src/intrinsics.def:70:6 /// @see src/builtins.def:70:6
class I32 : public TypeMatcher { class I32 : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -106,7 +106,7 @@ std::string I32::String(MatchState&) const {
} }
/// TypeMatcher for 'type u32' /// TypeMatcher for 'type u32'
/// @see src/intrinsics.def:71:6 /// @see src/builtins.def:71:6
class U32 : public TypeMatcher { class U32 : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -133,7 +133,7 @@ std::string U32::String(MatchState&) const {
} }
/// TypeMatcher for 'type vec2' /// TypeMatcher for 'type vec2'
/// @see src/intrinsics.def:72:6 /// @see src/builtins.def:72:6
class Vec2 : public TypeMatcher { class Vec2 : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -166,7 +166,7 @@ std::string Vec2::String(MatchState& state) const {
} }
/// TypeMatcher for 'type vec3' /// TypeMatcher for 'type vec3'
/// @see src/intrinsics.def:73:6 /// @see src/builtins.def:73:6
class Vec3 : public TypeMatcher { class Vec3 : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -199,7 +199,7 @@ std::string Vec3::String(MatchState& state) const {
} }
/// TypeMatcher for 'type vec4' /// TypeMatcher for 'type vec4'
/// @see src/intrinsics.def:74:6 /// @see src/builtins.def:74:6
class Vec4 : public TypeMatcher { class Vec4 : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -232,7 +232,7 @@ std::string Vec4::String(MatchState& state) const {
} }
/// TypeMatcher for 'type vec' /// TypeMatcher for 'type vec'
/// @see src/intrinsics.def:75:37 /// @see src/builtins.def:75:37
class Vec : public TypeMatcher { class Vec : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -273,7 +273,7 @@ std::string Vec::String(MatchState& state) const {
} }
/// TypeMatcher for 'type mat' /// TypeMatcher for 'type mat'
/// @see src/intrinsics.def:76:37 /// @see src/builtins.def:76:37
class Mat : public TypeMatcher { class Mat : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -320,7 +320,7 @@ std::string Mat::String(MatchState& state) const {
} }
/// TypeMatcher for 'type ptr' /// TypeMatcher for 'type ptr'
/// @see src/intrinsics.def:77:6 /// @see src/builtins.def:77:6
class Ptr : public TypeMatcher { class Ptr : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -365,7 +365,7 @@ std::string Ptr::String(MatchState& state) const {
} }
/// TypeMatcher for 'type atomic' /// TypeMatcher for 'type atomic'
/// @see src/intrinsics.def:78:6 /// @see src/builtins.def:78:6
class Atomic : public TypeMatcher { class Atomic : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -398,7 +398,7 @@ std::string Atomic::String(MatchState& state) const {
} }
/// TypeMatcher for 'type array' /// TypeMatcher for 'type array'
/// @see src/intrinsics.def:79:6 /// @see src/builtins.def:79:6
class Array : public TypeMatcher { class Array : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -431,7 +431,7 @@ std::string Array::String(MatchState& state) const {
} }
/// TypeMatcher for 'type sampler' /// TypeMatcher for 'type sampler'
/// @see src/intrinsics.def:80:6 /// @see src/builtins.def:80:6
class Sampler : public TypeMatcher { class Sampler : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -458,7 +458,7 @@ std::string Sampler::String(MatchState&) const {
} }
/// TypeMatcher for 'type sampler_comparison' /// TypeMatcher for 'type sampler_comparison'
/// @see src/intrinsics.def:81:6 /// @see src/builtins.def:81:6
class SamplerComparison : public TypeMatcher { class SamplerComparison : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -485,7 +485,7 @@ std::string SamplerComparison::String(MatchState&) const {
} }
/// TypeMatcher for 'type texture_1d' /// TypeMatcher for 'type texture_1d'
/// @see src/intrinsics.def:82:6 /// @see src/builtins.def:82:6
class Texture1D : public TypeMatcher { class Texture1D : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -518,7 +518,7 @@ std::string Texture1D::String(MatchState& state) const {
} }
/// TypeMatcher for 'type texture_2d' /// TypeMatcher for 'type texture_2d'
/// @see src/intrinsics.def:83:6 /// @see src/builtins.def:83:6
class Texture2D : public TypeMatcher { class Texture2D : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -551,7 +551,7 @@ std::string Texture2D::String(MatchState& state) const {
} }
/// TypeMatcher for 'type texture_2d_array' /// TypeMatcher for 'type texture_2d_array'
/// @see src/intrinsics.def:84:6 /// @see src/builtins.def:84:6
class Texture2DArray : public TypeMatcher { class Texture2DArray : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -584,7 +584,7 @@ std::string Texture2DArray::String(MatchState& state) const {
} }
/// TypeMatcher for 'type texture_3d' /// TypeMatcher for 'type texture_3d'
/// @see src/intrinsics.def:85:6 /// @see src/builtins.def:85:6
class Texture3D : public TypeMatcher { class Texture3D : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -617,7 +617,7 @@ std::string Texture3D::String(MatchState& state) const {
} }
/// TypeMatcher for 'type texture_cube' /// TypeMatcher for 'type texture_cube'
/// @see src/intrinsics.def:86:6 /// @see src/builtins.def:86:6
class TextureCube : public TypeMatcher { class TextureCube : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -650,7 +650,7 @@ std::string TextureCube::String(MatchState& state) const {
} }
/// TypeMatcher for 'type texture_cube_array' /// TypeMatcher for 'type texture_cube_array'
/// @see src/intrinsics.def:87:6 /// @see src/builtins.def:87:6
class TextureCubeArray : public TypeMatcher { class TextureCubeArray : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -683,7 +683,7 @@ std::string TextureCubeArray::String(MatchState& state) const {
} }
/// TypeMatcher for 'type texture_multisampled_2d' /// TypeMatcher for 'type texture_multisampled_2d'
/// @see src/intrinsics.def:88:6 /// @see src/builtins.def:88:6
class TextureMultisampled2D : public TypeMatcher { class TextureMultisampled2D : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -716,7 +716,7 @@ std::string TextureMultisampled2D::String(MatchState& state) const {
} }
/// TypeMatcher for 'type texture_depth_2d' /// TypeMatcher for 'type texture_depth_2d'
/// @see src/intrinsics.def:89:6 /// @see src/builtins.def:89:6
class TextureDepth2D : public TypeMatcher { class TextureDepth2D : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -743,7 +743,7 @@ std::string TextureDepth2D::String(MatchState&) const {
} }
/// TypeMatcher for 'type texture_depth_2d_array' /// TypeMatcher for 'type texture_depth_2d_array'
/// @see src/intrinsics.def:90:6 /// @see src/builtins.def:90:6
class TextureDepth2DArray : public TypeMatcher { class TextureDepth2DArray : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -770,7 +770,7 @@ std::string TextureDepth2DArray::String(MatchState&) const {
} }
/// TypeMatcher for 'type texture_depth_cube' /// TypeMatcher for 'type texture_depth_cube'
/// @see src/intrinsics.def:91:6 /// @see src/builtins.def:91:6
class TextureDepthCube : public TypeMatcher { class TextureDepthCube : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -797,7 +797,7 @@ std::string TextureDepthCube::String(MatchState&) const {
} }
/// TypeMatcher for 'type texture_depth_cube_array' /// TypeMatcher for 'type texture_depth_cube_array'
/// @see src/intrinsics.def:92:6 /// @see src/builtins.def:92:6
class TextureDepthCubeArray : public TypeMatcher { class TextureDepthCubeArray : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -824,7 +824,7 @@ std::string TextureDepthCubeArray::String(MatchState&) const {
} }
/// TypeMatcher for 'type texture_depth_multisampled_2d' /// TypeMatcher for 'type texture_depth_multisampled_2d'
/// @see src/intrinsics.def:93:6 /// @see src/builtins.def:93:6
class TextureDepthMultisampled2D : public TypeMatcher { class TextureDepthMultisampled2D : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -851,7 +851,7 @@ std::string TextureDepthMultisampled2D::String(MatchState&) const {
} }
/// TypeMatcher for 'type texture_storage_1d' /// TypeMatcher for 'type texture_storage_1d'
/// @see src/intrinsics.def:94:6 /// @see src/builtins.def:94:6
class TextureStorage1D : public TypeMatcher { class TextureStorage1D : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -890,7 +890,7 @@ std::string TextureStorage1D::String(MatchState& state) const {
} }
/// TypeMatcher for 'type texture_storage_2d' /// TypeMatcher for 'type texture_storage_2d'
/// @see src/intrinsics.def:95:6 /// @see src/builtins.def:95:6
class TextureStorage2D : public TypeMatcher { class TextureStorage2D : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -929,7 +929,7 @@ std::string TextureStorage2D::String(MatchState& state) const {
} }
/// TypeMatcher for 'type texture_storage_2d_array' /// TypeMatcher for 'type texture_storage_2d_array'
/// @see src/intrinsics.def:96:6 /// @see src/builtins.def:96:6
class TextureStorage2DArray : public TypeMatcher { class TextureStorage2DArray : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -968,7 +968,7 @@ std::string TextureStorage2DArray::String(MatchState& state) const {
} }
/// TypeMatcher for 'type texture_storage_3d' /// TypeMatcher for 'type texture_storage_3d'
/// @see src/intrinsics.def:97:6 /// @see src/builtins.def:97:6
class TextureStorage3D : public TypeMatcher { class TextureStorage3D : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -1007,7 +1007,7 @@ std::string TextureStorage3D::String(MatchState& state) const {
} }
/// TypeMatcher for 'type texture_external' /// TypeMatcher for 'type texture_external'
/// @see src/intrinsics.def:98:6 /// @see src/builtins.def:98:6
class TextureExternal : public TypeMatcher { class TextureExternal : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -1034,7 +1034,7 @@ std::string TextureExternal::String(MatchState&) const {
} }
/// TypeMatcher for 'type __modf_result' /// TypeMatcher for 'type __modf_result'
/// @see src/intrinsics.def:100:6 /// @see src/builtins.def:100:6
class ModfResult : public TypeMatcher { class ModfResult : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -1061,7 +1061,7 @@ std::string ModfResult::String(MatchState&) const {
} }
/// TypeMatcher for 'type __modf_result_vec' /// TypeMatcher for 'type __modf_result_vec'
/// @see src/intrinsics.def:101:42 /// @see src/builtins.def:101:42
class ModfResultVec : public TypeMatcher { class ModfResultVec : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -1096,7 +1096,7 @@ std::string ModfResultVec::String(MatchState& state) const {
} }
/// TypeMatcher for 'type __frexp_result' /// TypeMatcher for 'type __frexp_result'
/// @see src/intrinsics.def:102:6 /// @see src/builtins.def:102:6
class FrexpResult : public TypeMatcher { class FrexpResult : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -1123,7 +1123,7 @@ std::string FrexpResult::String(MatchState&) const {
} }
/// TypeMatcher for 'type __frexp_result_vec' /// TypeMatcher for 'type __frexp_result_vec'
/// @see src/intrinsics.def:103:43 /// @see src/builtins.def:103:43
class FrexpResultVec : public TypeMatcher { class FrexpResultVec : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules. /// Checks whether the given type matches the matcher rules.
@ -1158,7 +1158,7 @@ std::string FrexpResultVec::String(MatchState& state) const {
} }
/// TypeMatcher for 'match fiu32' /// TypeMatcher for 'match fiu32'
/// @see src/intrinsics.def:111:7 /// @see src/builtins.def:111:7
class Fiu32 : public TypeMatcher { class Fiu32 : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules, and returns the /// Checks whether the given type matches the matcher rules, and returns the
@ -1192,7 +1192,7 @@ std::string Fiu32::String(MatchState&) const {
} }
/// TypeMatcher for 'match iu32' /// TypeMatcher for 'match iu32'
/// @see src/intrinsics.def:112:7 /// @see src/builtins.def:112:7
class Iu32 : public TypeMatcher { class Iu32 : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules, and returns the /// Checks whether the given type matches the matcher rules, and returns the
@ -1223,7 +1223,7 @@ std::string Iu32::String(MatchState&) const {
} }
/// TypeMatcher for 'match scalar' /// TypeMatcher for 'match scalar'
/// @see src/intrinsics.def:113:7 /// @see src/builtins.def:113:7
class Scalar : public TypeMatcher { class Scalar : public TypeMatcher {
public: public:
/// Checks whether the given type matches the matcher rules, and returns the /// Checks whether the given type matches the matcher rules, and returns the
@ -1260,7 +1260,7 @@ std::string Scalar::String(MatchState&) const {
} }
/// EnumMatcher for 'match f32_texel_format' /// EnumMatcher for 'match f32_texel_format'
/// @see src/intrinsics.def:124:7 /// @see src/builtins.def:124:7
class F32TexelFormat : public NumberMatcher { class F32TexelFormat : public NumberMatcher {
public: public:
/// Checks whether the given number matches the enum matcher rules. /// Checks whether the given number matches the enum matcher rules.
@ -1293,7 +1293,7 @@ std::string F32TexelFormat::String(MatchState&) const {
} }
/// EnumMatcher for 'match i32_texel_format' /// EnumMatcher for 'match i32_texel_format'
/// @see src/intrinsics.def:126:7 /// @see src/builtins.def:126:7
class I32TexelFormat : public NumberMatcher { class I32TexelFormat : public NumberMatcher {
public: public:
/// Checks whether the given number matches the enum matcher rules. /// Checks whether the given number matches the enum matcher rules.
@ -1325,7 +1325,7 @@ std::string I32TexelFormat::String(MatchState&) const {
} }
/// EnumMatcher for 'match u32_texel_format' /// EnumMatcher for 'match u32_texel_format'
/// @see src/intrinsics.def:128:7 /// @see src/builtins.def:128:7
class U32TexelFormat : public NumberMatcher { class U32TexelFormat : public NumberMatcher {
public: public:
/// Checks whether the given number matches the enum matcher rules. /// Checks whether the given number matches the enum matcher rules.
@ -1357,7 +1357,7 @@ std::string U32TexelFormat::String(MatchState&) const {
} }
/// EnumMatcher for 'match write_only' /// EnumMatcher for 'match write_only'
/// @see src/intrinsics.def:131:7 /// @see src/builtins.def:131:7
class WriteOnly : public NumberMatcher { class WriteOnly : public NumberMatcher {
public: public:
/// Checks whether the given number matches the enum matcher rules. /// Checks whether the given number matches the enum matcher rules.
@ -1383,7 +1383,7 @@ std::string WriteOnly::String(MatchState&) const {
} }
/// EnumMatcher for 'match function_private_workgroup' /// EnumMatcher for 'match function_private_workgroup'
/// @see src/intrinsics.def:133:7 /// @see src/builtins.def:133:7
class FunctionPrivateWorkgroup : public NumberMatcher { class FunctionPrivateWorkgroup : public NumberMatcher {
public: public:
/// Checks whether the given number matches the enum matcher rules. /// Checks whether the given number matches the enum matcher rules.
@ -1413,7 +1413,7 @@ std::string FunctionPrivateWorkgroup::String(MatchState&) const {
} }
/// EnumMatcher for 'match workgroup_or_storage' /// EnumMatcher for 'match workgroup_or_storage'
/// @see src/intrinsics.def:134:7 /// @see src/builtins.def:134:7
class WorkgroupOrStorage : public NumberMatcher { class WorkgroupOrStorage : public NumberMatcher {
public: public:
/// Checks whether the given number matches the enum matcher rules. /// Checks whether the given number matches the enum matcher rules.
@ -8642,7 +8642,7 @@ constexpr OverloadInfo kOverloads[] = {
}, },
}; };
constexpr IntrinsicInfo kIntrinsics[] = { constexpr BuiltinInfo kBuiltins[] = {
{ {
/* [0] */ /* [0] */
/* fn abs<T : fiu32>(T) -> T */ /* fn abs<T : fiu32>(T) -> T */

View File

@ -1,10 +1,10 @@
{{- /* {{- /*
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Template file for use with tools/intrinsic-gen to generate intrinsic_table.inl Template file for use with tools/builtin-gen to generate builtin_table.inl
Used by IntrinsicTable.cc for intrinsic overload resolution. Used by BuiltinTable.cc for builtin overload resolution.
See: See:
* tools/cmd/intrinsic-gen/gen for structures used by this template * tools/cmd/builtin-gen/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax * https://golang.org/pkg/text/template/ for documentation on the template syntax
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
*/ -}} */ -}}
@ -23,7 +23,7 @@ See:
{{ end -}} {{ end -}}
{{- end -}} {{- end -}}
{{- with IntrinsicTable -}} {{- with BuiltinTable -}}
{{- template "Matchers" . }} {{- template "Matchers" . }}
constexpr MatcherIndex kMatcherIndices[] = { constexpr MatcherIndex kMatcherIndices[] = {
@ -106,7 +106,7 @@ constexpr OverloadInfo kOverloads[] = {
{{- end }} {{- end }}
}; };
constexpr IntrinsicInfo kIntrinsics[] = { constexpr BuiltinInfo kBuiltins[] = {
{{- range $i, $f := .Functions }} {{- range $i, $f := .Functions }}
{ {
/* [{{$i}}] */ /* [{{$i}}] */

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/intrinsic_table.h" #include "src/builtin_table.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "src/program_builder.h" #include "src/program_builder.h"
@ -30,65 +30,63 @@ namespace {
using ::testing::HasSubstr; using ::testing::HasSubstr;
using IntrinsicType = sem::IntrinsicType; using BuiltinType = sem::BuiltinType;
using Parameter = sem::Parameter; using Parameter = sem::Parameter;
using ParameterUsage = sem::ParameterUsage; using ParameterUsage = sem::ParameterUsage;
class IntrinsicTableTest : public testing::Test, public ProgramBuilder { class BuiltinTableTest : public testing::Test, public ProgramBuilder {
public: public:
std::unique_ptr<IntrinsicTable> table = IntrinsicTable::Create(*this); std::unique_ptr<BuiltinTable> table = BuiltinTable::Create(*this);
}; };
TEST_F(IntrinsicTableTest, MatchF32) { TEST_F(BuiltinTableTest, MatchF32) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* result = table->Lookup(IntrinsicType::kCos, {f32}, Source{}); auto* result = table->Lookup(BuiltinType::kCos, {f32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kCos); EXPECT_EQ(result->Type(), BuiltinType::kCos);
EXPECT_EQ(result->ReturnType(), f32); EXPECT_EQ(result->ReturnType(), f32);
ASSERT_EQ(result->Parameters().size(), 1u); ASSERT_EQ(result->Parameters().size(), 1u);
EXPECT_EQ(result->Parameters()[0]->Type(), f32); EXPECT_EQ(result->Parameters()[0]->Type(), f32);
} }
TEST_F(IntrinsicTableTest, MismatchF32) { TEST_F(BuiltinTableTest, MismatchF32) {
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* result = table->Lookup(IntrinsicType::kCos, {i32}, Source{}); auto* result = table->Lookup(BuiltinType::kCos, {i32}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, MatchU32) { TEST_F(BuiltinTableTest, MatchU32) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* u32 = create<sem::U32>(); auto* u32 = create<sem::U32>();
auto* vec2_f32 = create<sem::Vector>(f32, 2); auto* vec2_f32 = create<sem::Vector>(f32, 2);
auto* result = auto* result = table->Lookup(BuiltinType::kUnpack2x16float, {u32}, Source{});
table->Lookup(IntrinsicType::kUnpack2x16float, {u32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kUnpack2x16float); EXPECT_EQ(result->Type(), BuiltinType::kUnpack2x16float);
EXPECT_EQ(result->ReturnType(), vec2_f32); EXPECT_EQ(result->ReturnType(), vec2_f32);
ASSERT_EQ(result->Parameters().size(), 1u); ASSERT_EQ(result->Parameters().size(), 1u);
EXPECT_EQ(result->Parameters()[0]->Type(), u32); EXPECT_EQ(result->Parameters()[0]->Type(), u32);
} }
TEST_F(IntrinsicTableTest, MismatchU32) { TEST_F(BuiltinTableTest, MismatchU32) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* result = auto* result = table->Lookup(BuiltinType::kUnpack2x16float, {f32}, Source{});
table->Lookup(IntrinsicType::kUnpack2x16float, {f32}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, MatchI32) { TEST_F(BuiltinTableTest, MatchI32) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* vec4_f32 = create<sem::Vector>(f32, 4); auto* vec4_f32 = create<sem::Vector>(f32, 4);
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k1d, f32); auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k1d, f32);
auto* result = auto* result =
table->Lookup(IntrinsicType::kTextureLoad, {tex, i32, i32}, Source{}); table->Lookup(BuiltinType::kTextureLoad, {tex, i32, i32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kTextureLoad); EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
EXPECT_EQ(result->ReturnType(), vec4_f32); EXPECT_EQ(result->ReturnType(), vec4_f32);
ASSERT_EQ(result->Parameters().size(), 3u); ASSERT_EQ(result->Parameters().size(), 3u);
EXPECT_EQ(result->Parameters()[0]->Type(), tex); EXPECT_EQ(result->Parameters()[0]->Type(), tex);
@ -99,51 +97,49 @@ TEST_F(IntrinsicTableTest, MatchI32) {
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kLevel); EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kLevel);
} }
TEST_F(IntrinsicTableTest, MismatchI32) { TEST_F(BuiltinTableTest, MismatchI32) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k1d, f32); auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k1d, f32);
auto* result = auto* result = table->Lookup(BuiltinType::kTextureLoad, {tex, f32}, Source{});
table->Lookup(IntrinsicType::kTextureLoad, {tex, f32}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, MatchIU32AsI32) { TEST_F(BuiltinTableTest, MatchIU32AsI32) {
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* result = table->Lookup(IntrinsicType::kCountOneBits, {i32}, Source{}); auto* result = table->Lookup(BuiltinType::kCountOneBits, {i32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kCountOneBits); EXPECT_EQ(result->Type(), BuiltinType::kCountOneBits);
EXPECT_EQ(result->ReturnType(), i32); EXPECT_EQ(result->ReturnType(), i32);
ASSERT_EQ(result->Parameters().size(), 1u); ASSERT_EQ(result->Parameters().size(), 1u);
EXPECT_EQ(result->Parameters()[0]->Type(), i32); EXPECT_EQ(result->Parameters()[0]->Type(), i32);
} }
TEST_F(IntrinsicTableTest, MatchIU32AsU32) { TEST_F(BuiltinTableTest, MatchIU32AsU32) {
auto* u32 = create<sem::U32>(); auto* u32 = create<sem::U32>();
auto* result = table->Lookup(IntrinsicType::kCountOneBits, {u32}, Source{}); auto* result = table->Lookup(BuiltinType::kCountOneBits, {u32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kCountOneBits); EXPECT_EQ(result->Type(), BuiltinType::kCountOneBits);
EXPECT_EQ(result->ReturnType(), u32); EXPECT_EQ(result->ReturnType(), u32);
ASSERT_EQ(result->Parameters().size(), 1u); ASSERT_EQ(result->Parameters().size(), 1u);
EXPECT_EQ(result->Parameters()[0]->Type(), u32); EXPECT_EQ(result->Parameters()[0]->Type(), u32);
} }
TEST_F(IntrinsicTableTest, MismatchIU32) { TEST_F(BuiltinTableTest, MismatchIU32) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* result = table->Lookup(IntrinsicType::kCountOneBits, {f32}, Source{}); auto* result = table->Lookup(BuiltinType::kCountOneBits, {f32}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, MatchFIU32AsI32) { TEST_F(BuiltinTableTest, MatchFIU32AsI32) {
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* result = auto* result = table->Lookup(BuiltinType::kClamp, {i32, i32, i32}, Source{});
table->Lookup(IntrinsicType::kClamp, {i32, i32, i32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kClamp); EXPECT_EQ(result->Type(), BuiltinType::kClamp);
EXPECT_EQ(result->ReturnType(), i32); EXPECT_EQ(result->ReturnType(), i32);
ASSERT_EQ(result->Parameters().size(), 3u); ASSERT_EQ(result->Parameters().size(), 3u);
EXPECT_EQ(result->Parameters()[0]->Type(), i32); EXPECT_EQ(result->Parameters()[0]->Type(), i32);
@ -151,13 +147,12 @@ TEST_F(IntrinsicTableTest, MatchFIU32AsI32) {
EXPECT_EQ(result->Parameters()[2]->Type(), i32); EXPECT_EQ(result->Parameters()[2]->Type(), i32);
} }
TEST_F(IntrinsicTableTest, MatchFIU32AsU32) { TEST_F(BuiltinTableTest, MatchFIU32AsU32) {
auto* u32 = create<sem::U32>(); auto* u32 = create<sem::U32>();
auto* result = auto* result = table->Lookup(BuiltinType::kClamp, {u32, u32, u32}, Source{});
table->Lookup(IntrinsicType::kClamp, {u32, u32, u32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kClamp); EXPECT_EQ(result->Type(), BuiltinType::kClamp);
EXPECT_EQ(result->ReturnType(), u32); EXPECT_EQ(result->ReturnType(), u32);
ASSERT_EQ(result->Parameters().size(), 3u); ASSERT_EQ(result->Parameters().size(), 3u);
EXPECT_EQ(result->Parameters()[0]->Type(), u32); EXPECT_EQ(result->Parameters()[0]->Type(), u32);
@ -165,13 +160,12 @@ TEST_F(IntrinsicTableTest, MatchFIU32AsU32) {
EXPECT_EQ(result->Parameters()[2]->Type(), u32); EXPECT_EQ(result->Parameters()[2]->Type(), u32);
} }
TEST_F(IntrinsicTableTest, MatchFIU32AsF32) { TEST_F(BuiltinTableTest, MatchFIU32AsF32) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* result = auto* result = table->Lookup(BuiltinType::kClamp, {f32, f32, f32}, Source{});
table->Lookup(IntrinsicType::kClamp, {f32, f32, f32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kClamp); EXPECT_EQ(result->Type(), BuiltinType::kClamp);
EXPECT_EQ(result->ReturnType(), f32); EXPECT_EQ(result->ReturnType(), f32);
ASSERT_EQ(result->Parameters().size(), 3u); ASSERT_EQ(result->Parameters().size(), 3u);
EXPECT_EQ(result->Parameters()[0]->Type(), f32); EXPECT_EQ(result->Parameters()[0]->Type(), f32);
@ -179,22 +173,22 @@ TEST_F(IntrinsicTableTest, MatchFIU32AsF32) {
EXPECT_EQ(result->Parameters()[2]->Type(), f32); EXPECT_EQ(result->Parameters()[2]->Type(), f32);
} }
TEST_F(IntrinsicTableTest, MismatchFIU32) { TEST_F(BuiltinTableTest, MismatchFIU32) {
auto* bool_ = create<sem::Bool>(); auto* bool_ = create<sem::Bool>();
auto* result = auto* result =
table->Lookup(IntrinsicType::kClamp, {bool_, bool_, bool_}, Source{}); table->Lookup(BuiltinType::kClamp, {bool_, bool_, bool_}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, MatchBool) { TEST_F(BuiltinTableTest, MatchBool) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* bool_ = create<sem::Bool>(); auto* bool_ = create<sem::Bool>();
auto* result = auto* result =
table->Lookup(IntrinsicType::kSelect, {f32, f32, bool_}, Source{}); table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kSelect); EXPECT_EQ(result->Type(), BuiltinType::kSelect);
EXPECT_EQ(result->ReturnType(), f32); EXPECT_EQ(result->ReturnType(), f32);
ASSERT_EQ(result->Parameters().size(), 3u); ASSERT_EQ(result->Parameters().size(), 3u);
EXPECT_EQ(result->Parameters()[0]->Type(), f32); EXPECT_EQ(result->Parameters()[0]->Type(), f32);
@ -202,46 +196,43 @@ TEST_F(IntrinsicTableTest, MatchBool) {
EXPECT_EQ(result->Parameters()[2]->Type(), bool_); EXPECT_EQ(result->Parameters()[2]->Type(), bool_);
} }
TEST_F(IntrinsicTableTest, MismatchBool) { TEST_F(BuiltinTableTest, MismatchBool) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* result = auto* result = table->Lookup(BuiltinType::kSelect, {f32, f32, f32}, Source{});
table->Lookup(IntrinsicType::kSelect, {f32, f32, f32}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, MatchPointer) { TEST_F(BuiltinTableTest, MatchPointer) {
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* atomicI32 = create<sem::Atomic>(i32); auto* atomicI32 = create<sem::Atomic>(i32);
auto* ptr = create<sem::Pointer>(atomicI32, ast::StorageClass::kWorkgroup, auto* ptr = create<sem::Pointer>(atomicI32, ast::StorageClass::kWorkgroup,
ast::Access::kReadWrite); ast::Access::kReadWrite);
auto* result = table->Lookup(IntrinsicType::kAtomicLoad, {ptr}, Source{}); auto* result = table->Lookup(BuiltinType::kAtomicLoad, {ptr}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kAtomicLoad); EXPECT_EQ(result->Type(), BuiltinType::kAtomicLoad);
EXPECT_EQ(result->ReturnType(), i32); EXPECT_EQ(result->ReturnType(), i32);
ASSERT_EQ(result->Parameters().size(), 1u); ASSERT_EQ(result->Parameters().size(), 1u);
EXPECT_EQ(result->Parameters()[0]->Type(), ptr); EXPECT_EQ(result->Parameters()[0]->Type(), ptr);
} }
TEST_F(IntrinsicTableTest, MismatchPointer) { TEST_F(BuiltinTableTest, MismatchPointer) {
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* atomicI32 = create<sem::Atomic>(i32); auto* atomicI32 = create<sem::Atomic>(i32);
auto* result = auto* result = table->Lookup(BuiltinType::kAtomicLoad, {atomicI32}, Source{});
table->Lookup(IntrinsicType::kAtomicLoad, {atomicI32}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, MatchArray) { TEST_F(BuiltinTableTest, MatchArray) {
auto* arr = create<sem::Array>(create<sem::U32>(), 0, 4, 4, 4, 4); auto* arr = create<sem::Array>(create<sem::U32>(), 0, 4, 4, 4, 4);
auto* arr_ptr = create<sem::Pointer>(arr, ast::StorageClass::kStorage, auto* arr_ptr = create<sem::Pointer>(arr, ast::StorageClass::kStorage,
ast::Access::kReadWrite); ast::Access::kReadWrite);
auto* result = auto* result = table->Lookup(BuiltinType::kArrayLength, {arr_ptr}, Source{});
table->Lookup(IntrinsicType::kArrayLength, {arr_ptr}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kArrayLength); EXPECT_EQ(result->Type(), BuiltinType::kArrayLength);
EXPECT_TRUE(result->ReturnType()->Is<sem::U32>()); EXPECT_TRUE(result->ReturnType()->Is<sem::U32>());
ASSERT_EQ(result->Parameters().size(), 1u); ASSERT_EQ(result->Parameters().size(), 1u);
auto* param_type = result->Parameters()[0]->Type(); auto* param_type = result->Parameters()[0]->Type();
@ -249,24 +240,24 @@ TEST_F(IntrinsicTableTest, MatchArray) {
EXPECT_TRUE(param_type->As<sem::Pointer>()->StoreType()->Is<sem::Array>()); EXPECT_TRUE(param_type->As<sem::Pointer>()->StoreType()->Is<sem::Array>());
} }
TEST_F(IntrinsicTableTest, MismatchArray) { TEST_F(BuiltinTableTest, MismatchArray) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* result = table->Lookup(IntrinsicType::kArrayLength, {f32}, Source{}); auto* result = table->Lookup(BuiltinType::kArrayLength, {f32}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, MatchSampler) { TEST_F(BuiltinTableTest, MatchSampler) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* vec2_f32 = create<sem::Vector>(f32, 2); auto* vec2_f32 = create<sem::Vector>(f32, 2);
auto* vec4_f32 = create<sem::Vector>(f32, 4); auto* vec4_f32 = create<sem::Vector>(f32, 4);
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32); auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
auto* sampler = create<sem::Sampler>(ast::SamplerKind::kSampler); auto* sampler = create<sem::Sampler>(ast::SamplerKind::kSampler);
auto* result = table->Lookup(IntrinsicType::kTextureSample, auto* result = table->Lookup(BuiltinType::kTextureSample,
{tex, sampler, vec2_f32}, Source{}); {tex, sampler, vec2_f32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kTextureSample); EXPECT_EQ(result->Type(), BuiltinType::kTextureSample);
EXPECT_EQ(result->ReturnType(), vec4_f32); EXPECT_EQ(result->ReturnType(), vec4_f32);
ASSERT_EQ(result->Parameters().size(), 3u); ASSERT_EQ(result->Parameters().size(), 3u);
EXPECT_EQ(result->Parameters()[0]->Type(), tex); EXPECT_EQ(result->Parameters()[0]->Type(), tex);
@ -277,27 +268,27 @@ TEST_F(IntrinsicTableTest, MatchSampler) {
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kCoords); EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kCoords);
} }
TEST_F(IntrinsicTableTest, MismatchSampler) { TEST_F(BuiltinTableTest, MismatchSampler) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* vec2_f32 = create<sem::Vector>(f32, 2); auto* vec2_f32 = create<sem::Vector>(f32, 2);
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32); auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
auto* result = table->Lookup(IntrinsicType::kTextureSample, auto* result = table->Lookup(BuiltinType::kTextureSample,
{tex, f32, vec2_f32}, Source{}); {tex, f32, vec2_f32}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, MatchSampledTexture) { TEST_F(BuiltinTableTest, MatchSampledTexture) {
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* vec2_i32 = create<sem::Vector>(i32, 2); auto* vec2_i32 = create<sem::Vector>(i32, 2);
auto* vec4_f32 = create<sem::Vector>(f32, 4); auto* vec4_f32 = create<sem::Vector>(f32, 4);
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32); auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
auto* result = table->Lookup(IntrinsicType::kTextureLoad, auto* result =
{tex, vec2_i32, i32}, Source{}); table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kTextureLoad); EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
EXPECT_EQ(result->ReturnType(), vec4_f32); EXPECT_EQ(result->ReturnType(), vec4_f32);
ASSERT_EQ(result->Parameters().size(), 3u); ASSERT_EQ(result->Parameters().size(), 3u);
EXPECT_EQ(result->Parameters()[0]->Type(), tex); EXPECT_EQ(result->Parameters()[0]->Type(), tex);
@ -308,17 +299,17 @@ TEST_F(IntrinsicTableTest, MatchSampledTexture) {
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kLevel); EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kLevel);
} }
TEST_F(IntrinsicTableTest, MatchMultisampledTexture) { TEST_F(BuiltinTableTest, MatchMultisampledTexture) {
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* vec2_i32 = create<sem::Vector>(i32, 2); auto* vec2_i32 = create<sem::Vector>(i32, 2);
auto* vec4_f32 = create<sem::Vector>(f32, 4); auto* vec4_f32 = create<sem::Vector>(f32, 4);
auto* tex = create<sem::MultisampledTexture>(ast::TextureDimension::k2d, f32); auto* tex = create<sem::MultisampledTexture>(ast::TextureDimension::k2d, f32);
auto* result = table->Lookup(IntrinsicType::kTextureLoad, auto* result =
{tex, vec2_i32, i32}, Source{}); table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kTextureLoad); EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
EXPECT_EQ(result->ReturnType(), vec4_f32); EXPECT_EQ(result->ReturnType(), vec4_f32);
ASSERT_EQ(result->Parameters().size(), 3u); ASSERT_EQ(result->Parameters().size(), 3u);
EXPECT_EQ(result->Parameters()[0]->Type(), tex); EXPECT_EQ(result->Parameters()[0]->Type(), tex);
@ -329,16 +320,16 @@ TEST_F(IntrinsicTableTest, MatchMultisampledTexture) {
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kSampleIndex); EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kSampleIndex);
} }
TEST_F(IntrinsicTableTest, MatchDepthTexture) { TEST_F(BuiltinTableTest, MatchDepthTexture) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* vec2_i32 = create<sem::Vector>(i32, 2); auto* vec2_i32 = create<sem::Vector>(i32, 2);
auto* tex = create<sem::DepthTexture>(ast::TextureDimension::k2d); auto* tex = create<sem::DepthTexture>(ast::TextureDimension::k2d);
auto* result = table->Lookup(IntrinsicType::kTextureLoad, auto* result =
{tex, vec2_i32, i32}, Source{}); table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kTextureLoad); EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
EXPECT_EQ(result->ReturnType(), f32); EXPECT_EQ(result->ReturnType(), f32);
ASSERT_EQ(result->Parameters().size(), 3u); ASSERT_EQ(result->Parameters().size(), 3u);
EXPECT_EQ(result->Parameters()[0]->Type(), tex); EXPECT_EQ(result->Parameters()[0]->Type(), tex);
@ -349,16 +340,16 @@ TEST_F(IntrinsicTableTest, MatchDepthTexture) {
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kLevel); EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kLevel);
} }
TEST_F(IntrinsicTableTest, MatchDepthMultisampledTexture) { TEST_F(BuiltinTableTest, MatchDepthMultisampledTexture) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* vec2_i32 = create<sem::Vector>(i32, 2); auto* vec2_i32 = create<sem::Vector>(i32, 2);
auto* tex = create<sem::DepthMultisampledTexture>(ast::TextureDimension::k2d); auto* tex = create<sem::DepthMultisampledTexture>(ast::TextureDimension::k2d);
auto* result = table->Lookup(IntrinsicType::kTextureLoad, auto* result =
{tex, vec2_i32, i32}, Source{}); table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kTextureLoad); EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
EXPECT_EQ(result->ReturnType(), f32); EXPECT_EQ(result->ReturnType(), f32);
ASSERT_EQ(result->Parameters().size(), 3u); ASSERT_EQ(result->Parameters().size(), 3u);
EXPECT_EQ(result->Parameters()[0]->Type(), tex); EXPECT_EQ(result->Parameters()[0]->Type(), tex);
@ -369,17 +360,17 @@ TEST_F(IntrinsicTableTest, MatchDepthMultisampledTexture) {
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kSampleIndex); EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kSampleIndex);
} }
TEST_F(IntrinsicTableTest, MatchExternalTexture) { TEST_F(BuiltinTableTest, MatchExternalTexture) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* vec2_i32 = create<sem::Vector>(i32, 2); auto* vec2_i32 = create<sem::Vector>(i32, 2);
auto* vec4_f32 = create<sem::Vector>(f32, 4); auto* vec4_f32 = create<sem::Vector>(f32, 4);
auto* tex = create<sem::ExternalTexture>(); auto* tex = create<sem::ExternalTexture>();
auto* result = auto* result =
table->Lookup(IntrinsicType::kTextureLoad, {tex, vec2_i32}, Source{}); table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kTextureLoad); EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
EXPECT_EQ(result->ReturnType(), vec4_f32); EXPECT_EQ(result->ReturnType(), vec4_f32);
ASSERT_EQ(result->Parameters().size(), 2u); ASSERT_EQ(result->Parameters().size(), 2u);
EXPECT_EQ(result->Parameters()[0]->Type(), tex); EXPECT_EQ(result->Parameters()[0]->Type(), tex);
@ -388,7 +379,7 @@ TEST_F(IntrinsicTableTest, MatchExternalTexture) {
EXPECT_EQ(result->Parameters()[1]->Usage(), ParameterUsage::kCoords); EXPECT_EQ(result->Parameters()[1]->Usage(), ParameterUsage::kCoords);
} }
TEST_F(IntrinsicTableTest, MatchWOStorageTexture) { TEST_F(BuiltinTableTest, MatchWOStorageTexture) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* vec2_i32 = create<sem::Vector>(i32, 2); auto* vec2_i32 = create<sem::Vector>(i32, 2);
@ -399,11 +390,11 @@ TEST_F(IntrinsicTableTest, MatchWOStorageTexture) {
ast::TexelFormat::kR32Float, ast::TexelFormat::kR32Float,
ast::Access::kWrite, subtype); ast::Access::kWrite, subtype);
auto* result = table->Lookup(IntrinsicType::kTextureStore, auto* result = table->Lookup(BuiltinType::kTextureStore,
{tex, vec2_i32, vec4_f32}, Source{}); {tex, vec2_i32, vec4_f32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kTextureStore); EXPECT_EQ(result->Type(), BuiltinType::kTextureStore);
EXPECT_TRUE(result->ReturnType()->Is<sem::Void>()); EXPECT_TRUE(result->ReturnType()->Is<sem::Void>());
ASSERT_EQ(result->Parameters().size(), 3u); ASSERT_EQ(result->Parameters().size(), 3u);
EXPECT_EQ(result->Parameters()[0]->Type(), tex); EXPECT_EQ(result->Parameters()[0]->Type(), tex);
@ -414,61 +405,59 @@ TEST_F(IntrinsicTableTest, MatchWOStorageTexture) {
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kValue); EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kValue);
} }
TEST_F(IntrinsicTableTest, MismatchTexture) { TEST_F(BuiltinTableTest, MismatchTexture) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* vec2_i32 = create<sem::Vector>(i32, 2); auto* vec2_i32 = create<sem::Vector>(i32, 2);
auto* result = auto* result =
table->Lookup(IntrinsicType::kTextureLoad, {f32, vec2_i32}, Source{}); table->Lookup(BuiltinType::kTextureLoad, {f32, vec2_i32}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) { TEST_F(BuiltinTableTest, ImplicitLoadOnReference) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* result = auto* result =
table->Lookup(IntrinsicType::kCos, table->Lookup(BuiltinType::kCos,
{create<sem::Reference>(f32, ast::StorageClass::kFunction, {create<sem::Reference>(f32, ast::StorageClass::kFunction,
ast::Access::kReadWrite)}, ast::Access::kReadWrite)},
Source{}); Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kCos); EXPECT_EQ(result->Type(), BuiltinType::kCos);
EXPECT_EQ(result->ReturnType(), f32); EXPECT_EQ(result->ReturnType(), f32);
ASSERT_EQ(result->Parameters().size(), 1u); ASSERT_EQ(result->Parameters().size(), 1u);
EXPECT_EQ(result->Parameters()[0]->Type(), f32); EXPECT_EQ(result->Parameters()[0]->Type(), f32);
} }
TEST_F(IntrinsicTableTest, MatchOpenType) { TEST_F(BuiltinTableTest, MatchOpenType) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* result = auto* result = table->Lookup(BuiltinType::kClamp, {f32, f32, f32}, Source{});
table->Lookup(IntrinsicType::kClamp, {f32, f32, f32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kClamp); EXPECT_EQ(result->Type(), BuiltinType::kClamp);
EXPECT_EQ(result->ReturnType(), f32); EXPECT_EQ(result->ReturnType(), f32);
EXPECT_EQ(result->Parameters()[0]->Type(), f32); EXPECT_EQ(result->Parameters()[0]->Type(), f32);
EXPECT_EQ(result->Parameters()[1]->Type(), f32); EXPECT_EQ(result->Parameters()[1]->Type(), f32);
EXPECT_EQ(result->Parameters()[2]->Type(), f32); EXPECT_EQ(result->Parameters()[2]->Type(), f32);
} }
TEST_F(IntrinsicTableTest, MismatchOpenType) { TEST_F(BuiltinTableTest, MismatchOpenType) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* u32 = create<sem::U32>(); auto* u32 = create<sem::U32>();
auto* result = auto* result = table->Lookup(BuiltinType::kClamp, {f32, u32, f32}, Source{});
table->Lookup(IntrinsicType::kClamp, {f32, u32, f32}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, MatchOpenSizeVector) { TEST_F(BuiltinTableTest, MatchOpenSizeVector) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* vec2_f32 = create<sem::Vector>(f32, 2); auto* vec2_f32 = create<sem::Vector>(f32, 2);
auto* result = table->Lookup(IntrinsicType::kClamp, auto* result = table->Lookup(BuiltinType::kClamp,
{vec2_f32, vec2_f32, vec2_f32}, Source{}); {vec2_f32, vec2_f32, vec2_f32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kClamp); EXPECT_EQ(result->Type(), BuiltinType::kClamp);
EXPECT_EQ(result->ReturnType(), vec2_f32); EXPECT_EQ(result->ReturnType(), vec2_f32);
ASSERT_EQ(result->Parameters().size(), 3u); ASSERT_EQ(result->Parameters().size(), 3u);
EXPECT_EQ(result->Parameters()[0]->Type(), vec2_f32); EXPECT_EQ(result->Parameters()[0]->Type(), vec2_f32);
@ -476,45 +465,44 @@ TEST_F(IntrinsicTableTest, MatchOpenSizeVector) {
EXPECT_EQ(result->Parameters()[2]->Type(), vec2_f32); EXPECT_EQ(result->Parameters()[2]->Type(), vec2_f32);
} }
TEST_F(IntrinsicTableTest, MismatchOpenSizeVector) { TEST_F(BuiltinTableTest, MismatchOpenSizeVector) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* u32 = create<sem::U32>(); auto* u32 = create<sem::U32>();
auto* vec2_f32 = create<sem::Vector>(f32, 2); auto* vec2_f32 = create<sem::Vector>(f32, 2);
auto* result = auto* result =
table->Lookup(IntrinsicType::kClamp, {vec2_f32, u32, vec2_f32}, Source{}); table->Lookup(BuiltinType::kClamp, {vec2_f32, u32, vec2_f32}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, MatchOpenSizeMatrix) { TEST_F(BuiltinTableTest, MatchOpenSizeMatrix) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* vec3_f32 = create<sem::Vector>(f32, 3); auto* vec3_f32 = create<sem::Vector>(f32, 3);
auto* mat3_f32 = create<sem::Matrix>(vec3_f32, 3); auto* mat3_f32 = create<sem::Matrix>(vec3_f32, 3);
auto* result = auto* result = table->Lookup(BuiltinType::kDeterminant, {mat3_f32}, Source{});
table->Lookup(IntrinsicType::kDeterminant, {mat3_f32}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_EQ(result->Type(), IntrinsicType::kDeterminant); EXPECT_EQ(result->Type(), BuiltinType::kDeterminant);
EXPECT_EQ(result->ReturnType(), f32); EXPECT_EQ(result->ReturnType(), f32);
ASSERT_EQ(result->Parameters().size(), 1u); ASSERT_EQ(result->Parameters().size(), 1u);
EXPECT_EQ(result->Parameters()[0]->Type(), mat3_f32); EXPECT_EQ(result->Parameters()[0]->Type(), mat3_f32);
} }
TEST_F(IntrinsicTableTest, MismatchOpenSizeMatrix) { TEST_F(BuiltinTableTest, MismatchOpenSizeMatrix) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* vec2_f32 = create<sem::Vector>(f32, 2); auto* vec2_f32 = create<sem::Vector>(f32, 2);
auto* mat3x2_f32 = create<sem::Matrix>(vec2_f32, 3); auto* mat3x2_f32 = create<sem::Matrix>(vec2_f32, 3);
auto* result = auto* result =
table->Lookup(IntrinsicType::kDeterminant, {mat3x2_f32}, Source{}); table->Lookup(BuiltinType::kDeterminant, {mat3x2_f32}, Source{});
ASSERT_EQ(result, nullptr); ASSERT_EQ(result, nullptr);
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call")); ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
} }
TEST_F(IntrinsicTableTest, OverloadOrderByNumberOfParameters) { TEST_F(BuiltinTableTest, OverloadOrderByNumberOfParameters) {
// None of the arguments match, so expect the overloads with 2 parameters to // None of the arguments match, so expect the overloads with 2 parameters to
// come first // come first
auto* bool_ = create<sem::Bool>(); auto* bool_ = create<sem::Bool>();
table->Lookup(IntrinsicType::kTextureDimensions, {bool_, bool_}, Source{}); table->Lookup(BuiltinType::kTextureDimensions, {bool_, bool_}, Source{});
ASSERT_EQ(Diagnostics().str(), ASSERT_EQ(Diagnostics().str(),
R"(error: no matching call to textureDimensions(bool, bool) R"(error: no matching call to textureDimensions(bool, bool)
@ -549,10 +537,10 @@ TEST_F(IntrinsicTableTest, OverloadOrderByNumberOfParameters) {
)"); )");
} }
TEST_F(IntrinsicTableTest, OverloadOrderByMatchingParameter) { TEST_F(BuiltinTableTest, OverloadOrderByMatchingParameter) {
auto* tex = create<sem::DepthTexture>(ast::TextureDimension::k2d); auto* tex = create<sem::DepthTexture>(ast::TextureDimension::k2d);
auto* bool_ = create<sem::Bool>(); auto* bool_ = create<sem::Bool>();
table->Lookup(IntrinsicType::kTextureDimensions, {tex, bool_}, Source{}); table->Lookup(BuiltinType::kTextureDimensions, {tex, bool_}, Source{});
ASSERT_EQ( ASSERT_EQ(
Diagnostics().str(), Diagnostics().str(),
R"(error: no matching call to textureDimensions(texture_depth_2d, bool) R"(error: no matching call to textureDimensions(texture_depth_2d, bool)
@ -588,18 +576,18 @@ TEST_F(IntrinsicTableTest, OverloadOrderByMatchingParameter) {
)"); )");
} }
TEST_F(IntrinsicTableTest, SameOverloadReturnsSameIntrinsicPointer) { TEST_F(BuiltinTableTest, SameOverloadReturnsSameBuiltinPointer) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* vec2_f32 = create<sem::Vector>(create<sem::F32>(), 2); auto* vec2_f32 = create<sem::Vector>(create<sem::F32>(), 2);
auto* bool_ = create<sem::Bool>(); auto* bool_ = create<sem::Bool>();
auto* a = table->Lookup(IntrinsicType::kSelect, {f32, f32, bool_}, Source{}); auto* a = table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
ASSERT_NE(a, nullptr) << Diagnostics().str(); ASSERT_NE(a, nullptr) << Diagnostics().str();
auto* b = table->Lookup(IntrinsicType::kSelect, {f32, f32, bool_}, Source{}); auto* b = table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
ASSERT_NE(b, nullptr) << Diagnostics().str(); ASSERT_NE(b, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
auto* c = table->Lookup(IntrinsicType::kSelect, {vec2_f32, vec2_f32, bool_}, auto* c = table->Lookup(BuiltinType::kSelect, {vec2_f32, vec2_f32, bool_},
Source{}); Source{});
ASSERT_NE(c, nullptr) << Diagnostics().str(); ASSERT_NE(c, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");

View File

@ -13,9 +13,9 @@
// limitations under the License. // limitations under the License.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// WGSL intrinsic definition file // // WGSL builtin definition file //
// // // //
// This file is used to generate parts of the Tint IntrinsicTable, various // // This file is used to generate parts of the Tint BuiltinTable, various //
// enum definition files, as well as test .wgsl files. // // enum definition files, as well as test .wgsl files. //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -134,10 +134,10 @@ match function_private_workgroup: function | private | workgroup
match workgroup_or_storage: workgroup | storage match workgroup_or_storage: workgroup | storage
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Intrinsic Functions // // Builtin Functions //
// // // //
// The intrinsic function declarations below declare all the built-in // // The builtin function declarations below declare all the built-in //
// functions supported by the WGSL language. This intrinsic definition // // functions supported by the WGSL language. This builtin definition //
// language supports simple static-type function declarations, as well as // // language supports simple static-type function declarations, as well as //
// single overload declarations that can match a number of different // // single overload declarations that can match a number of different //
// argument types via the use of 'open-types' and 'open-numbers'. // // argument types via the use of 'open-types' and 'open-numbers'. //
@ -150,7 +150,7 @@ match workgroup_or_storage: workgroup | storage
// parameter of type 'f32' and returns a 'bool'. // // parameter of type 'f32' and returns a 'bool'. //
// // // //
// An 'open-type' can be thought as a template type that is determined by the // // An 'open-type' can be thought as a template type that is determined by the //
// arguments to the intrinsic. // // arguments to the builtin. //
// // // //
// * Open-type example without constraint: // // * Open-type example without constraint: //
// // // //
@ -170,7 +170,7 @@ match workgroup_or_storage: workgroup | storage
// same argument type. // // same argument type. //
// // // //
// Similarly an 'open-number' can be thought as a template number or // // Similarly an 'open-number' can be thought as a template number or //
// enumerator that is determined by the arguments to the intrinsic. // // enumerator that is determined by the arguments to the builtin. //
// // // //
// * Open-number example: // // * Open-number example: //
// // // //
@ -239,7 +239,7 @@ match workgroup_or_storage: workgroup | storage
// fn F(USAGE : f32) // // fn F(USAGE : f32) //
// - Single parameter with name USAGE. // // - Single parameter with name USAGE. //
// Note: Parameter names are used by Tint to infer parameter order for // // Note: Parameter names are used by Tint to infer parameter order for //
// some intrinsic functions // // some builtin functions //
// // // //
// fn F<T>(T) // // fn F<T>(T) //
// - Single parameter of unconstrained open-type T (any type) // // - Single parameter of unconstrained open-type T (any type) //

View File

@ -785,7 +785,7 @@ void Inspector::GenerateSamplerTargets() {
continue; continue;
} }
auto* i = call->Target()->As<sem::Intrinsic>(); auto* i = call->Target()->As<sem::Builtin>();
if (!i) { if (!i) {
continue; continue;
} }

View File

@ -1,53 +0,0 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_INTRINSIC_TABLE_H_
#define SRC_INTRINSIC_TABLE_H_
#include <memory>
#include <string>
#include <vector>
#include "src/sem/intrinsic.h"
namespace tint {
// Forward declarations
class ProgramBuilder;
/// IntrinsicTable is a lookup table of all the WGSL intrinsic functions
class IntrinsicTable {
public:
/// @param builder the program builder
/// @return a pointer to a newly created IntrinsicTable
static std::unique_ptr<IntrinsicTable> Create(ProgramBuilder& builder);
/// Destructor
virtual ~IntrinsicTable();
/// Lookup looks for the intrinsic overload with the given signature, raising
/// an error diagnostic if the intrinsic was not found.
/// @param type the intrinsic type
/// @param args the argument types passed to the intrinsic function
/// @param source the source of the intrinsic call
/// @return the semantic intrinsic if found, otherwise nullptr
virtual const sem::Intrinsic* Lookup(
sem::IntrinsicType type,
const std::vector<const sem::Type*>& args,
const Source& source) = 0;
};
} // namespace tint
#endif // SRC_INTRINSIC_TABLE_H_

View File

@ -33,8 +33,8 @@
#include "src/ast/switch_statement.h" #include "src/ast/switch_statement.h"
#include "src/ast/unary_op_expression.h" #include "src/ast/unary_op_expression.h"
#include "src/ast/variable_decl_statement.h" #include "src/ast/variable_decl_statement.h"
#include "src/sem/builtin_type.h"
#include "src/sem/depth_texture_type.h" #include "src/sem/depth_texture_type.h"
#include "src/sem/intrinsic_type.h"
#include "src/sem/sampled_texture_type.h" #include "src/sem/sampled_texture_type.h"
// Terms: // Terms:
@ -437,38 +437,38 @@ std::string GetGlslStd450FuncName(uint32_t ext_opcode) {
return ""; return "";
} }
// Returns the WGSL standard library function intrinsic for the // Returns the WGSL standard library function builtin for the
// given instruction, or sem::IntrinsicType::kNone // given instruction, or sem::BuiltinType::kNone
sem::IntrinsicType GetIntrinsic(SpvOp opcode) { sem::BuiltinType GetBuiltin(SpvOp opcode) {
switch (opcode) { switch (opcode) {
case SpvOpBitCount: case SpvOpBitCount:
return sem::IntrinsicType::kCountOneBits; return sem::BuiltinType::kCountOneBits;
case SpvOpBitReverse: case SpvOpBitReverse:
return sem::IntrinsicType::kReverseBits; return sem::BuiltinType::kReverseBits;
case SpvOpDot: case SpvOpDot:
return sem::IntrinsicType::kDot; return sem::BuiltinType::kDot;
case SpvOpDPdx: case SpvOpDPdx:
return sem::IntrinsicType::kDpdx; return sem::BuiltinType::kDpdx;
case SpvOpDPdy: case SpvOpDPdy:
return sem::IntrinsicType::kDpdy; return sem::BuiltinType::kDpdy;
case SpvOpFwidth: case SpvOpFwidth:
return sem::IntrinsicType::kFwidth; return sem::BuiltinType::kFwidth;
case SpvOpDPdxFine: case SpvOpDPdxFine:
return sem::IntrinsicType::kDpdxFine; return sem::BuiltinType::kDpdxFine;
case SpvOpDPdyFine: case SpvOpDPdyFine:
return sem::IntrinsicType::kDpdyFine; return sem::BuiltinType::kDpdyFine;
case SpvOpFwidthFine: case SpvOpFwidthFine:
return sem::IntrinsicType::kFwidthFine; return sem::BuiltinType::kFwidthFine;
case SpvOpDPdxCoarse: case SpvOpDPdxCoarse:
return sem::IntrinsicType::kDpdxCoarse; return sem::BuiltinType::kDpdxCoarse;
case SpvOpDPdyCoarse: case SpvOpDPdyCoarse:
return sem::IntrinsicType::kDpdyCoarse; return sem::BuiltinType::kDpdyCoarse;
case SpvOpFwidthCoarse: case SpvOpFwidthCoarse:
return sem::IntrinsicType::kFwidthCoarse; return sem::BuiltinType::kFwidthCoarse;
default: default:
break; break;
} }
return sem::IntrinsicType::kNone; return sem::BuiltinType::kNone;
} }
// @param opcode a SPIR-V opcode // @param opcode a SPIR-V opcode
@ -3888,9 +3888,9 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
std::move(params))}; std::move(params))};
} }
const auto intrinsic = GetIntrinsic(opcode); const auto builtin = GetBuiltin(opcode);
if (intrinsic != sem::IntrinsicType::kNone) { if (builtin != sem::BuiltinType::kNone) {
return MakeIntrinsicCall(inst); return MakeBuiltinCall(inst);
} }
if (opcode == SpvOpFMod) { if (opcode == SpvOpFMod) {
@ -5081,10 +5081,10 @@ bool FunctionEmitter::EmitControlBarrier(
return true; return true;
} }
TypedExpression FunctionEmitter::MakeIntrinsicCall( TypedExpression FunctionEmitter::MakeBuiltinCall(
const spvtools::opt::Instruction& inst) { const spvtools::opt::Instruction& inst) {
const auto intrinsic = GetIntrinsic(inst.opcode()); const auto builtin = GetBuiltin(inst.opcode());
auto* name = sem::str(intrinsic); auto* name = sem::str(builtin);
auto* ident = create<ast::IdentifierExpression>( auto* ident = create<ast::IdentifierExpression>(
Source{}, builder_.Symbols().Register(name)); Source{}, builder_.Symbols().Register(name));
@ -5864,7 +5864,7 @@ TypedExpression FunctionEmitter::MakeArrayLength(
auto* member_access = create<ast::MemberAccessorExpression>( auto* member_access = create<ast::MemberAccessorExpression>(
Source{}, member_expr.expr, member_ident); Source{}, member_expr.expr, member_ident);
// Generate the intrinsic function call. // Generate the builtin function call.
auto* call_expr = auto* call_expr =
builder_.Call(Source{}, "arrayLength", builder_.AddressOf(member_access)); builder_.Call(Source{}, "arrayLength", builder_.AddressOf(member_access));

View File

@ -995,17 +995,17 @@ class FunctionEmitter {
/// @returns false if emission failed /// @returns false if emission failed
bool EmitFunctionCall(const spvtools::opt::Instruction& inst); bool EmitFunctionCall(const spvtools::opt::Instruction& inst);
/// Emits a control barrier intrinsic. On failure, emits a diagnostic and /// Emits a control barrier builtin. On failure, emits a diagnostic and
/// returns false. /// returns false.
/// @param inst the SPIR-V control barrier instruction /// @param inst the SPIR-V control barrier instruction
/// @returns false if emission failed /// @returns false if emission failed
bool EmitControlBarrier(const spvtools::opt::Instruction& inst); bool EmitControlBarrier(const spvtools::opt::Instruction& inst);
/// Returns an expression for a SPIR-V instruction that maps to a WGSL /// Returns an expression for a SPIR-V instruction that maps to a WGSL
/// intrinsic function call. /// builtin function call.
/// @param inst the SPIR-V instruction /// @param inst the SPIR-V instruction
/// @returns an expression /// @returns an expression
TypedExpression MakeIntrinsicCall(const spvtools::opt::Instruction& inst); TypedExpression MakeBuiltinCall(const spvtools::opt::Instruction& inst);
/// Returns an expression for a SPIR-V OpArrayLength instruction. /// Returns an expression for a SPIR-V OpArrayLength instruction.
/// @param inst the SPIR-V instruction /// @param inst the SPIR-V instruction

View File

@ -935,11 +935,11 @@ TEST_F(SpvBinaryArithTestBasic, OuterProduct) {
<< got; << got;
} }
struct IntrinsicData { struct BuiltinData {
const std::string spirv; const std::string spirv;
const std::string wgsl; const std::string wgsl;
}; };
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) { inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
out << "OpData{" << data.spirv << "," << data.wgsl << "}"; out << "OpData{" << data.spirv << "," << data.wgsl << "}";
return out; return out;
} }
@ -955,10 +955,10 @@ inline std::ostream& operator<<(std::ostream& out, ArgAndTypeData data) {
} }
using SpvBinaryDerivativeTest = SpvParserTestBase< using SpvBinaryDerivativeTest = SpvParserTestBase<
::testing::TestWithParam<std::tuple<IntrinsicData, ArgAndTypeData>>>; ::testing::TestWithParam<std::tuple<BuiltinData, ArgAndTypeData>>>;
TEST_P(SpvBinaryDerivativeTest, Derivatives) { TEST_P(SpvBinaryDerivativeTest, Derivatives) {
auto& intrinsic = std::get<0>(GetParam()); auto& builtin = std::get<0>(GetParam());
auto& arg = std::get<1>(GetParam()); auto& arg = std::get<1>(GetParam());
const auto assembly = R"( const auto assembly = R"(
@ -968,7 +968,7 @@ TEST_P(SpvBinaryDerivativeTest, Derivatives) {
%entry = OpLabel %entry = OpLabel
%1 = OpCopyObject %)" + %1 = OpCopyObject %)" +
arg.spirv_type + " %" + arg.spirv_arg + R"( arg.spirv_type + " %" + arg.spirv_arg + R"(
%2 = )" + intrinsic.spirv + %2 = )" + builtin.spirv +
" %" + arg.spirv_type + R"( %1 " %" + arg.spirv_type + R"( %1
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
@ -979,24 +979,24 @@ TEST_P(SpvBinaryDerivativeTest, Derivatives) {
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error(); EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body(); auto ast_body = fe.ast_body();
EXPECT_THAT(test::ToString(p->program(), ast_body), EXPECT_THAT(
HasSubstr("let x_2 : " + arg.ast_type + " = " + intrinsic.wgsl + test::ToString(p->program(), ast_body),
"(x_1);")); HasSubstr("let x_2 : " + arg.ast_type + " = " + builtin.wgsl + "(x_1);"));
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
SpvBinaryDerivativeTest, SpvBinaryDerivativeTest,
SpvBinaryDerivativeTest, SpvBinaryDerivativeTest,
testing::Combine( testing::Combine(
::testing::Values(IntrinsicData{"OpDPdx", "dpdx"}, ::testing::Values(BuiltinData{"OpDPdx", "dpdx"},
IntrinsicData{"OpDPdy", "dpdy"}, BuiltinData{"OpDPdy", "dpdy"},
IntrinsicData{"OpFwidth", "fwidth"}, BuiltinData{"OpFwidth", "fwidth"},
IntrinsicData{"OpDPdxFine", "dpdxFine"}, BuiltinData{"OpDPdxFine", "dpdxFine"},
IntrinsicData{"OpDPdyFine", "dpdyFine"}, BuiltinData{"OpDPdyFine", "dpdyFine"},
IntrinsicData{"OpFwidthFine", "fwidthFine"}, BuiltinData{"OpFwidthFine", "fwidthFine"},
IntrinsicData{"OpDPdxCoarse", "dpdxCoarse"}, BuiltinData{"OpDPdxCoarse", "dpdxCoarse"},
IntrinsicData{"OpDPdyCoarse", "dpdyCoarse"}, BuiltinData{"OpDPdyCoarse", "dpdyCoarse"},
IntrinsicData{"OpFwidthCoarse", "fwidthCoarse"}), BuiltinData{"OpFwidthCoarse", "fwidthCoarse"}),
::testing::Values( ::testing::Values(
ArgAndTypeData{"float", "float_50", "f32"}, ArgAndTypeData{"float", "float_50", "f32"},
ArgAndTypeData{"v2float", "v2float_50_60", "vec2<f32>"}, ArgAndTypeData{"v2float", "v2float_50_60", "vec2<f32>"},

View File

@ -74,9 +74,9 @@ TEST_F(SpvParserTest, WorkgroupBarrier) {
EXPECT_EQ(call->expr->args.size(), 0u); EXPECT_EQ(call->expr->args.size(), 0u);
auto* sem_call = program.Sem().Get(call->expr); auto* sem_call = program.Sem().Get(call->expr);
ASSERT_NE(sem_call, nullptr); ASSERT_NE(sem_call, nullptr);
auto* intrinsic = sem_call->Target()->As<sem::Intrinsic>(); auto* builtin = sem_call->Target()->As<sem::Builtin>();
ASSERT_NE(intrinsic, nullptr); ASSERT_NE(builtin, nullptr);
EXPECT_EQ(intrinsic->Type(), sem::IntrinsicType::kWorkgroupBarrier); EXPECT_EQ(builtin->Type(), sem::BuiltinType::kWorkgroupBarrier);
} }
TEST_F(SpvParserTest, StorageBarrier) { TEST_F(SpvParserTest, StorageBarrier) {
@ -108,9 +108,9 @@ TEST_F(SpvParserTest, StorageBarrier) {
EXPECT_EQ(call->expr->args.size(), 0u); EXPECT_EQ(call->expr->args.size(), 0u);
auto* sem_call = program.Sem().Get(call->expr); auto* sem_call = program.Sem().Get(call->expr);
ASSERT_NE(sem_call, nullptr); ASSERT_NE(sem_call, nullptr);
auto* intrinsic = sem_call->Target()->As<sem::Intrinsic>(); auto* builtin = sem_call->Target()->As<sem::Builtin>();
ASSERT_NE(intrinsic, nullptr); ASSERT_NE(builtin, nullptr);
EXPECT_EQ(intrinsic->Type(), sem::IntrinsicType::kStorageBarrier); EXPECT_EQ(builtin->Type(), sem::BuiltinType::kStorageBarrier);
} }
TEST_F(SpvParserTest, ErrBarrierInvalidExecution) { TEST_F(SpvParserTest, ErrBarrierInvalidExecution) {

View File

@ -114,7 +114,7 @@ fn f() { a = 1 }
)"); )");
} }
TEST_F(ParserImplErrorTest, AssignmentStmtInvalidLHS_IntrinsicFunctionName) { TEST_F(ParserImplErrorTest, AssignmentStmtInvalidLHS_BuiltinFunctionName) {
EXPECT("normalize = 5;", EXPECT("normalize = 5;",
R"(test.wgsl:1:1 error: statement found outside of function body R"(test.wgsl:1:1 error: statement found outside of function body
normalize = 5; normalize = 5;

View File

@ -12,16 +12,16 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/intrinsic_texture_helper_test.h" #include "src/ast/builtin_texture_helper_test.h"
#include "src/resolver/resolver_test_helper.h" #include "src/resolver/resolver_test_helper.h"
namespace tint { namespace tint {
namespace resolver { namespace resolver {
namespace { namespace {
using ResolverIntrinsicValidationTest = ResolverTest; using ResolverBuiltinValidationTest = ResolverTest;
TEST_F(ResolverIntrinsicValidationTest, TEST_F(ResolverBuiltinValidationTest,
FunctionTypeMustMatchReturnStatementType_void_fail) { FunctionTypeMustMatchReturnStatementType_void_fail) {
// fn func { return workgroupBarrier(); } // fn func { return workgroupBarrier(); }
Func("func", {}, ty.void_(), Func("func", {}, ty.void_(),
@ -30,12 +30,11 @@ TEST_F(ResolverIntrinsicValidationTest,
}); });
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(r()->error(),
r()->error(), "12:34 error: builtin 'workgroupBarrier' does not return a value");
"12:34 error: intrinsic 'workgroupBarrier' does not return a value");
} }
TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageDirect) { TEST_F(ResolverBuiltinValidationTest, InvalidPipelineStageDirect) {
// @stage(compute) @workgroup_size(1) fn func { return dpdx(1.0); } // @stage(compute) @workgroup_size(1) fn func { return dpdx(1.0); }
auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"), auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"),
@ -49,7 +48,7 @@ TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageDirect) {
"3:4 error: built-in cannot be used by compute pipeline stage"); "3:4 error: built-in cannot be used by compute pipeline stage");
} }
TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageIndirect) { TEST_F(ResolverBuiltinValidationTest, InvalidPipelineStageIndirect) {
// fn f0 { return dpdx(1.0); } // fn f0 { return dpdx(1.0); }
// fn f1 { f0(); } // fn f1 { f0(); }
// fn f2 { f1(); } // fn f2 { f1(); }
@ -75,7 +74,7 @@ TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageIndirect) {
7:8 note: called by entry point 'main')"); 7:8 note: called by entry point 'main')");
} }
TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsFunction) { TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsFunction) {
Func(Source{{12, 34}}, "mix", {}, ty.i32(), {}); Func(Source{{12, 34}}, "mix", {}, ty.i32(), {});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -84,7 +83,7 @@ TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsFunction) {
R"(12:34 error: 'mix' is a builtin and cannot be redeclared as a function)"); R"(12:34 error: 'mix' is a builtin and cannot be redeclared as a function)");
} }
TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsGlobalLet) { TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsGlobalLet) {
GlobalConst(Source{{12, 34}}, "mix", ty.i32(), Expr(1)); GlobalConst(Source{{12, 34}}, "mix", ty.i32(), Expr(1));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -93,7 +92,7 @@ TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsGlobalLet) {
R"(12:34 error: 'mix' is a builtin and cannot be redeclared as a module-scope let)"); R"(12:34 error: 'mix' is a builtin and cannot be redeclared as a module-scope let)");
} }
TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsGlobalVar) { TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsGlobalVar) {
Global(Source{{12, 34}}, "mix", ty.i32(), Expr(1), Global(Source{{12, 34}}, "mix", ty.i32(), Expr(1),
ast::StorageClass::kPrivate); ast::StorageClass::kPrivate);
@ -103,7 +102,7 @@ TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsGlobalVar) {
R"(12:34 error: 'mix' is a builtin and cannot be redeclared as a module-scope var)"); R"(12:34 error: 'mix' is a builtin and cannot be redeclared as a module-scope var)");
} }
TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsAlias) { TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsAlias) {
Alias(Source{{12, 34}}, "mix", ty.i32()); Alias(Source{{12, 34}}, "mix", ty.i32());
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -112,7 +111,7 @@ TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsAlias) {
R"(12:34 error: 'mix' is a builtin and cannot be redeclared as an alias)"); R"(12:34 error: 'mix' is a builtin and cannot be redeclared as an alias)");
} }
TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsStruct) { TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsStruct) {
Structure(Source{{12, 34}}, "mix", {Member("m", ty.i32())}); Structure(Source{{12, 34}}, "mix", {Member("m", ty.i32())});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -123,10 +122,10 @@ TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsStruct) {
namespace texture_constexpr_args { namespace texture_constexpr_args {
using TextureOverloadCase = ast::intrinsic::test::TextureOverloadCase; using TextureOverloadCase = ast::builtin::test::TextureOverloadCase;
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload; using ValidTextureOverload = ast::builtin::test::ValidTextureOverload;
using TextureKind = ast::intrinsic::test::TextureKind; using TextureKind = ast::builtin::test::TextureKind;
using TextureDataType = ast::intrinsic::test::TextureDataType; using TextureDataType = ast::builtin::test::TextureDataType;
using u32 = ProgramBuilder::u32; using u32 = ProgramBuilder::u32;
using i32 = ProgramBuilder::i32; using i32 = ProgramBuilder::i32;
using f32 = ProgramBuilder::f32; using f32 = ProgramBuilder::f32;
@ -229,10 +228,10 @@ static std::ostream& operator<<(std::ostream& out, Constexpr expr) {
return out; return out;
} }
using IntrinsicTextureConstExprArgValidationTest = ResolverTestWithParam< using BuiltinTextureConstExprArgValidationTest = ResolverTestWithParam<
std::tuple<TextureOverloadCase, Parameter, Constexpr>>; std::tuple<TextureOverloadCase, Parameter, Constexpr>>;
TEST_P(IntrinsicTextureConstExprArgValidationTest, Immediate) { TEST_P(BuiltinTextureConstExprArgValidationTest, Immediate) {
auto& p = GetParam(); auto& p = GetParam();
auto overload = std::get<0>(p); auto overload = std::get<0>(p);
auto param = std::get<1>(p); auto param = std::get<1>(p);
@ -255,7 +254,7 @@ TEST_P(IntrinsicTextureConstExprArgValidationTest, Immediate) {
arg_to_replace = expr(Source{{12, 34}}, *this); arg_to_replace = expr(Source{{12, 34}}, *this);
// Call the intrinsic with the constexpr argument replaced // Call the builtin with the constexpr argument replaced
Func("func", {}, ty.void_(), {CallStmt(Call(overload.function, args))}, Func("func", {}, ty.void_(), {CallStmt(Call(overload.function, args))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -279,7 +278,7 @@ TEST_P(IntrinsicTextureConstExprArgValidationTest, Immediate) {
} }
} }
TEST_P(IntrinsicTextureConstExprArgValidationTest, GlobalConst) { TEST_P(BuiltinTextureConstExprArgValidationTest, GlobalConst) {
auto& p = GetParam(); auto& p = GetParam();
auto overload = std::get<0>(p); auto overload = std::get<0>(p);
auto param = std::get<1>(p); auto param = std::get<1>(p);
@ -302,7 +301,7 @@ TEST_P(IntrinsicTextureConstExprArgValidationTest, GlobalConst) {
arg_to_replace = Expr(Source{{12, 34}}, "G"); arg_to_replace = Expr(Source{{12, 34}}, "G");
// Call the intrinsic with the constexpr argument replaced // Call the builtin with the constexpr argument replaced
Func("func", {}, ty.void_(), {CallStmt(Call(overload.function, args))}, Func("func", {}, ty.void_(), {CallStmt(Call(overload.function, args))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -315,7 +314,7 @@ TEST_P(IntrinsicTextureConstExprArgValidationTest, GlobalConst) {
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
Offset2D, Offset2D,
IntrinsicTextureConstExprArgValidationTest, BuiltinTextureConstExprArgValidationTest,
testing::Combine( testing::Combine(
testing::ValuesIn(TextureCases({ testing::ValuesIn(TextureCases({
ValidTextureOverload::kSample2dOffsetF32, ValidTextureOverload::kSample2dOffsetF32,
@ -349,7 +348,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
Offset3D, Offset3D,
IntrinsicTextureConstExprArgValidationTest, BuiltinTextureConstExprArgValidationTest,
testing::Combine( testing::Combine(
testing::ValuesIn(TextureCases({ testing::ValuesIn(TextureCases({
ValidTextureOverload::kSample3dOffsetF32, ValidTextureOverload::kSample3dOffsetF32,
@ -377,7 +376,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
Component, Component,
IntrinsicTextureConstExprArgValidationTest, BuiltinTextureConstExprArgValidationTest,
testing::Combine( testing::Combine(
testing::ValuesIn( testing::ValuesIn(
TextureCases({ValidTextureOverload::kGather2dF32, TextureCases({ValidTextureOverload::kGather2dF32,

View File

@ -24,7 +24,7 @@
#include "src/ast/fallthrough_statement.h" #include "src/ast/fallthrough_statement.h"
#include "src/ast/traverse_expressions.h" #include "src/ast/traverse_expressions.h"
#include "src/scope_stack.h" #include "src/scope_stack.h"
#include "src/sem/intrinsic.h" #include "src/sem/builtin.h"
#include "src/utils/defer.h" #include "src/utils/defer.h"
#include "src/utils/map.h" #include "src/utils/map.h"
#include "src/utils/scoped_assignment.h" #include "src/utils/scoped_assignment.h"
@ -297,7 +297,7 @@ class DependencyScanner {
if (auto* ident = expr->As<ast::IdentifierExpression>()) { if (auto* ident = expr->As<ast::IdentifierExpression>()) {
auto* node = scope_stack_.Get(ident->symbol); auto* node = scope_stack_.Get(ident->symbol);
if (node == nullptr) { if (node == nullptr) {
if (!IsIntrinsic(ident->symbol)) { if (!IsBuiltin(ident->symbol)) {
UnknownSymbol(ident->symbol, ident->source, "identifier"); UnknownSymbol(ident->symbol, ident->source, "identifier");
} }
return ast::TraverseAction::Descend; return ast::TraverseAction::Descend;
@ -313,7 +313,7 @@ class DependencyScanner {
} }
if (auto* call = expr->As<ast::CallExpression>()) { if (auto* call = expr->As<ast::CallExpression>()) {
if (call->target.name) { if (call->target.name) {
if (!IsIntrinsic(call->target.name->symbol)) { if (!IsBuiltin(call->target.name->symbol)) {
AddGlobalDependency(call->target.name, AddGlobalDependency(call->target.name,
call->target.name->symbol, "function", call->target.name->symbol, "function",
"calls"); "calls");
@ -436,10 +436,10 @@ class DependencyScanner {
} }
} }
/// @returns true if `name` is the name of an intrinsic function /// @returns true if `name` is the name of a builtin function
bool IsIntrinsic(Symbol name) const { bool IsBuiltin(Symbol name) const {
return sem::ParseIntrinsicType(symbols_.NameFor(name)) != return sem::ParseBuiltinType(symbols_.NameFor(name)) !=
sem::IntrinsicType::kNone; sem::BuiltinType::kNone;
} }
/// Appends an error to the diagnostics that the given symbol cannot be /// Appends an error to the diagnostics that the given symbol cannot be

View File

@ -84,7 +84,7 @@ namespace resolver {
Resolver::Resolver(ProgramBuilder* builder) Resolver::Resolver(ProgramBuilder* builder)
: builder_(builder), : builder_(builder),
diagnostics_(builder->Diagnostics()), diagnostics_(builder->Diagnostics()),
intrinsic_table_(IntrinsicTable::Create(*builder)) {} builtin_table_(BuiltinTable::Create(*builder)) {}
Resolver::~Resolver() = default; Resolver::~Resolver() = default;
@ -1354,10 +1354,9 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
} }
auto name = builder_->Symbols().NameFor(ident->symbol); auto name = builder_->Symbols().NameFor(ident->symbol);
auto intrinsic_type = sem::ParseIntrinsicType(name); auto builtin_type = sem::ParseBuiltinType(name);
if (intrinsic_type != sem::IntrinsicType::kNone) { if (builtin_type != sem::BuiltinType::kNone) {
return IntrinsicCall(expr, intrinsic_type, std::move(args), return BuiltinCall(expr, builtin_type, std::move(args), std::move(arg_tys));
std::move(arg_tys));
} }
TINT_ICE(Resolver, diagnostics_) TINT_ICE(Resolver, diagnostics_)
@ -1368,36 +1367,35 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
return nullptr; return nullptr;
} }
sem::Call* Resolver::IntrinsicCall( sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
const ast::CallExpression* expr, sem::BuiltinType builtin_type,
sem::IntrinsicType intrinsic_type, const std::vector<const sem::Expression*> args,
const std::vector<const sem::Expression*> args, const std::vector<const sem::Type*> arg_tys) {
const std::vector<const sem::Type*> arg_tys) { auto* builtin =
auto* intrinsic = intrinsic_table_->Lookup(intrinsic_type, std::move(arg_tys), builtin_table_->Lookup(builtin_type, std::move(arg_tys), expr->source);
expr->source); if (!builtin) {
if (!intrinsic) {
return nullptr; return nullptr;
} }
if (intrinsic->IsDeprecated()) { if (builtin->IsDeprecated()) {
AddWarning("use of deprecated intrinsic", expr->source); AddWarning("use of deprecated builtin", expr->source);
} }
auto* call = builder_->create<sem::Call>(expr, intrinsic, std::move(args), auto* call = builder_->create<sem::Call>(expr, builtin, std::move(args),
current_statement_, sem::Constant{}); current_statement_, sem::Constant{});
current_function_->AddDirectlyCalledIntrinsic(intrinsic); current_function_->AddDirectlyCalledBuiltin(builtin);
if (IsTextureIntrinsic(intrinsic_type)) { if (IsTextureBuiltin(builtin_type)) {
if (!ValidateTextureIntrinsicFunction(call)) { if (!ValidateTextureBuiltinFunction(call)) {
return nullptr; return nullptr;
} }
// Collect a texture/sampler pair for this intrinsic. // Collect a texture/sampler pair for this builtin.
const auto& signature = intrinsic->Signature(); const auto& signature = builtin->Signature();
int texture_index = signature.IndexOf(sem::ParameterUsage::kTexture); int texture_index = signature.IndexOf(sem::ParameterUsage::kTexture);
if (texture_index == -1) { if (texture_index == -1) {
TINT_ICE(Resolver, diagnostics_) TINT_ICE(Resolver, diagnostics_)
<< "texture intrinsic without texture parameter"; << "texture builtin without texture parameter";
} }
auto* texture = args[texture_index]->As<sem::VariableUser>()->Variable(); auto* texture = args[texture_index]->As<sem::VariableUser>()->Variable();
@ -1409,7 +1407,7 @@ sem::Call* Resolver::IntrinsicCall(
current_function_->AddTextureSamplerPair(texture, sampler); current_function_->AddTextureSamplerPair(texture, sampler);
} }
if (!ValidateIntrinsicCall(call)) { if (!ValidateBuiltinCall(call)) {
return nullptr; return nullptr;
} }
@ -1662,8 +1660,8 @@ sem::Expression* Resolver::Identifier(const ast::IdentifierExpression* expr) {
return nullptr; return nullptr;
} }
if (IsIntrinsic(symbol)) { if (IsBuiltin(symbol)) {
AddError("missing '(' for intrinsic call", expr->source.End()); AddError("missing '(' for builtin call", expr->source.End());
return nullptr; return nullptr;
} }
@ -2786,9 +2784,9 @@ bool Resolver::IsHostShareable(const sem::Type* type) const {
return false; return false;
} }
bool Resolver::IsIntrinsic(Symbol symbol) const { bool Resolver::IsBuiltin(Symbol symbol) const {
std::string name = builder_->Symbols().NameFor(symbol); std::string name = builder_->Symbols().NameFor(symbol);
return sem::ParseIntrinsicType(name) != sem::IntrinsicType::kNone; return sem::ParseBuiltinType(name) != sem::BuiltinType::kNone;
} }
bool Resolver::IsCallStatement(const ast::Expression* expr) const { bool Resolver::IsCallStatement(const ast::Expression* expr) const {

View File

@ -23,7 +23,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "src/intrinsic_table.h" #include "src/builtin_table.h"
#include "src/program_builder.h" #include "src/program_builder.h"
#include "src/resolver/dependency_graph.h" #include "src/resolver/dependency_graph.h"
#include "src/scope_stack.h" #include "src/scope_stack.h"
@ -59,11 +59,11 @@ namespace sem {
class Array; class Array;
class Atomic; class Atomic;
class BlockStatement; class BlockStatement;
class Builtin;
class CaseStatement; class CaseStatement;
class ElseStatement; class ElseStatement;
class ForLoopStatement; class ForLoopStatement;
class IfStatement; class IfStatement;
class Intrinsic;
class LoopStatement; class LoopStatement;
class Statement; class Statement;
class SwitchStatement; class SwitchStatement;
@ -191,10 +191,10 @@ class Resolver {
const std::vector<const sem::Expression*> args, const std::vector<const sem::Expression*> args,
sem::Behaviors arg_behaviors); sem::Behaviors arg_behaviors);
sem::Expression* Identifier(const ast::IdentifierExpression*); sem::Expression* Identifier(const ast::IdentifierExpression*);
sem::Call* IntrinsicCall(const ast::CallExpression*, sem::Call* BuiltinCall(const ast::CallExpression*,
sem::IntrinsicType, sem::BuiltinType,
const std::vector<const sem::Expression*> args, const std::vector<const sem::Expression*> args,
const std::vector<const sem::Type*> arg_tys); const std::vector<const sem::Type*> arg_tys);
sem::Expression* Literal(const ast::LiteralExpression*); sem::Expression* Literal(const ast::LiteralExpression*);
sem::Expression* MemberAccessor(const ast::MemberAccessorExpression*); sem::Expression* MemberAccessor(const ast::MemberAccessorExpression*);
sem::Call* TypeConversion(const ast::CallExpression* expr, sem::Call* TypeConversion(const ast::CallExpression* expr,
@ -258,7 +258,7 @@ class Resolver {
bool ValidateIfStatement(const sem::IfStatement* stmt); bool ValidateIfStatement(const sem::IfStatement* stmt);
bool ValidateInterpolateAttribute(const ast::InterpolateAttribute* attr, bool ValidateInterpolateAttribute(const ast::InterpolateAttribute* attr,
const sem::Type* storage_type); const sem::Type* storage_type);
bool ValidateIntrinsicCall(const sem::Call* call); bool ValidateBuiltinCall(const sem::Call* call);
bool ValidateLocationAttribute(const ast::LocationAttribute* location, bool ValidateLocationAttribute(const ast::LocationAttribute* location,
const sem::Type* type, const sem::Type* type,
std::unordered_set<uint32_t>& locations, std::unordered_set<uint32_t>& locations,
@ -290,7 +290,7 @@ class Resolver {
const sem::Type* type); const sem::Type* type);
bool ValidateArrayConstructorOrCast(const ast::CallExpression* ctor, bool ValidateArrayConstructorOrCast(const ast::CallExpression* ctor,
const sem::Array* arr_type); const sem::Array* arr_type);
bool ValidateTextureIntrinsicFunction(const sem::Call* call); bool ValidateTextureBuiltinFunction(const sem::Call* call);
bool ValidateNoDuplicateAttributes(const ast::AttributeList& attributes); bool ValidateNoDuplicateAttributes(const ast::AttributeList& attributes);
bool ValidateStorageClassLayout(const sem::Type* type, bool ValidateStorageClassLayout(const sem::Type* type,
ast::StorageClass sc, ast::StorageClass sc,
@ -462,9 +462,8 @@ class Resolver {
return const_cast<T*>(As<T>(sem)); return const_cast<T*>(As<T>(sem));
} }
/// @returns true if the symbol is the name of an intrinsic (builtin) /// @returns true if the symbol is the name of a builtin function.
/// function. bool IsBuiltin(Symbol) const;
bool IsIntrinsic(Symbol) const;
/// @returns true if `expr` is the current CallStatement's CallExpression /// @returns true if `expr` is the current CallStatement's CallExpression
bool IsCallStatement(const ast::Expression* expr) const; bool IsCallStatement(const ast::Expression* expr) const;
@ -520,7 +519,7 @@ class Resolver {
ProgramBuilder* const builder_; ProgramBuilder* const builder_;
diag::List& diagnostics_; diag::List& diagnostics_;
std::unique_ptr<IntrinsicTable> const intrinsic_table_; std::unique_ptr<BuiltinTable> const builtin_table_;
DependencyGraph dependencies_; DependencyGraph dependencies_;
std::vector<sem::Function*> entry_points_; std::vector<sem::Function*> entry_points_;
std::unordered_map<const sem::Type*, const Source&> atomic_composite_info_; std::unordered_map<const sem::Type*, const Source&> atomic_composite_info_;

View File

@ -21,11 +21,11 @@
#include "src/ast/assignment_statement.h" #include "src/ast/assignment_statement.h"
#include "src/ast/bitcast_expression.h" #include "src/ast/bitcast_expression.h"
#include "src/ast/break_statement.h" #include "src/ast/break_statement.h"
#include "src/ast/builtin_texture_helper_test.h"
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/continue_statement.h" #include "src/ast/continue_statement.h"
#include "src/ast/float_literal_expression.h" #include "src/ast/float_literal_expression.h"
#include "src/ast/if_statement.h" #include "src/ast/if_statement.h"
#include "src/ast/intrinsic_texture_helper_test.h"
#include "src/ast/loop_statement.h" #include "src/ast/loop_statement.h"
#include "src/ast/override_attribute.h" #include "src/ast/override_attribute.h"
#include "src/ast/return_statement.h" #include "src/ast/return_statement.h"
@ -535,7 +535,7 @@ TEST_F(ResolverTest, Expr_Call_WithParams) {
EXPECT_TRUE(TypeOf(param)->Is<sem::F32>()); EXPECT_TRUE(TypeOf(param)->Is<sem::F32>());
} }
TEST_F(ResolverTest, Expr_Call_Intrinsic) { TEST_F(ResolverTest, Expr_Call_Builtin) {
auto* call = Call("round", 2.4f); auto* call = Call("round", 2.4f);
WrapInFunction(call); WrapInFunction(call);

View File

@ -560,7 +560,7 @@ bool Resolver::ValidateVariable(const sem::Variable* var) {
if (var->Is<sem::GlobalVariable>()) { if (var->Is<sem::GlobalVariable>()) {
auto name = builder_->Symbols().NameFor(decl->symbol); auto name = builder_->Symbols().NameFor(decl->symbol);
if (sem::ParseIntrinsicType(name) != sem::IntrinsicType::kNone) { if (sem::ParseBuiltinType(name) != sem::BuiltinType::kNone) {
auto* kind = var->Declaration()->is_const ? "let" : "var"; auto* kind = var->Declaration()->is_const ? "let" : "var";
AddError( AddError(
"'" + name + "'" + name +
@ -840,7 +840,7 @@ bool Resolver::ValidateFunction(const sem::Function* func) {
auto* decl = func->Declaration(); auto* decl = func->Declaration();
auto name = builder_->Symbols().NameFor(decl->symbol); auto name = builder_->Symbols().NameFor(decl->symbol);
if (sem::ParseIntrinsicType(name) != sem::IntrinsicType::kNone) { if (sem::ParseBuiltinType(name) != sem::BuiltinType::kNone) {
AddError( AddError(
"'" + name + "' is a builtin and cannot be redeclared as a function", "'" + name + "' is a builtin and cannot be redeclared as a function",
decl->source); decl->source);
@ -1369,7 +1369,7 @@ bool Resolver::ValidateIfStatement(const sem::IfStatement* stmt) {
return true; return true;
} }
bool Resolver::ValidateIntrinsicCall(const sem::Call* call) { bool Resolver::ValidateBuiltinCall(const sem::Call* call) {
if (call->Type()->Is<sem::Void>()) { if (call->Type()->Is<sem::Void>()) {
bool is_call_statement = false; bool is_call_statement = false;
if (auto* call_stmt = As<ast::CallStatement>(call->Stmt()->Declaration())) { if (auto* call_stmt = As<ast::CallStatement>(call->Stmt()->Declaration())) {
@ -1383,7 +1383,7 @@ bool Resolver::ValidateIntrinsicCall(const sem::Call* call) {
// statement should be used instead. // statement should be used instead.
auto* ident = call->Declaration()->target.name; auto* ident = call->Declaration()->target.name;
auto name = builder_->Symbols().NameFor(ident->symbol); auto name = builder_->Symbols().NameFor(ident->symbol);
AddError("intrinsic '" + name + "' does not return a value", AddError("builtin '" + name + "' does not return a value",
call->Declaration()->source); call->Declaration()->source);
return false; return false;
} }
@ -1392,14 +1392,14 @@ bool Resolver::ValidateIntrinsicCall(const sem::Call* call) {
return true; return true;
} }
bool Resolver::ValidateTextureIntrinsicFunction(const sem::Call* call) { bool Resolver::ValidateTextureBuiltinFunction(const sem::Call* call) {
auto* intrinsic = call->Target()->As<sem::Intrinsic>(); auto* builtin = call->Target()->As<sem::Builtin>();
if (!intrinsic) { if (!builtin) {
return false; return false;
} }
std::string func_name = intrinsic->str(); std::string func_name = builtin->str();
auto& signature = intrinsic->Signature(); auto& signature = builtin->Signature();
auto check_arg_is_constexpr = [&](sem::ParameterUsage usage, int min, auto check_arg_is_constexpr = [&](sem::ParameterUsage usage, int min,
int max) { int max) {
@ -1431,7 +1431,7 @@ bool Resolver::ValidateTextureIntrinsicFunction(const sem::Call* call) {
return ast::TraverseAction::Stop; return ast::TraverseAction::Stop;
}); });
if (is_const_expr) { if (is_const_expr) {
auto vector = intrinsic->Parameters()[index]->Type()->Is<sem::Vector>(); auto vector = builtin->Parameters()[index]->Type()->Is<sem::Vector>();
for (size_t i = 0; i < values.Elements().size(); i++) { for (size_t i = 0; i < values.Elements().size(); i++) {
auto value = values.Elements()[i].i32; auto value = values.Elements()[i].i32;
if (value < min || value > max) { if (value < min || value > max) {
@ -1895,12 +1895,12 @@ bool Resolver::ValidatePipelineStages() {
} }
} }
auto check_intrinsic_calls = [&](const sem::Function* func, auto check_builtin_calls = [&](const sem::Function* func,
const sem::Function* entry_point) { const sem::Function* entry_point) {
auto stage = entry_point->Declaration()->PipelineStage(); auto stage = entry_point->Declaration()->PipelineStage();
for (auto* intrinsic : func->DirectlyCalledIntrinsics()) { for (auto* builtin : func->DirectlyCalledBuiltins()) {
if (!intrinsic->SupportedStages().Contains(stage)) { if (!builtin->SupportedStages().Contains(stage)) {
auto* call = func->FindDirectCallTo(intrinsic); auto* call = func->FindDirectCallTo(builtin);
std::stringstream err; std::stringstream err;
err << "built-in cannot be used by " << stage << " pipeline stage"; err << "built-in cannot be used by " << stage << " pipeline stage";
AddError(err.str(), call ? call->Declaration()->source AddError(err.str(), call ? call->Declaration()->source
@ -1927,11 +1927,11 @@ bool Resolver::ValidatePipelineStages() {
}; };
for (auto* entry_point : entry_points_) { for (auto* entry_point : entry_points_) {
if (!check_intrinsic_calls(entry_point, entry_point)) { if (!check_builtin_calls(entry_point, entry_point)) {
return false; return false;
} }
for (auto* func : entry_point->TransitivelyCalledFunctions()) { for (auto* func : entry_point->TransitivelyCalledFunctions()) {
if (!check_intrinsic_calls(func, entry_point)) { if (!check_builtin_calls(func, entry_point)) {
return false; return false;
} }
} }
@ -1974,7 +1974,7 @@ bool Resolver::ValidateArrayStrideAttribute(const ast::StrideAttribute* attr,
bool Resolver::ValidateAlias(const ast::Alias* alias) { bool Resolver::ValidateAlias(const ast::Alias* alias) {
auto name = builder_->Symbols().NameFor(alias->name); auto name = builder_->Symbols().NameFor(alias->name);
if (sem::ParseIntrinsicType(name) != sem::IntrinsicType::kNone) { if (sem::ParseBuiltinType(name) != sem::BuiltinType::kNone) {
AddError("'" + name + "' is a builtin and cannot be redeclared as an alias", AddError("'" + name + "' is a builtin and cannot be redeclared as an alias",
alias->source); alias->source);
return false; return false;
@ -1985,7 +1985,7 @@ bool Resolver::ValidateAlias(const ast::Alias* alias) {
bool Resolver::ValidateStructure(const sem::Struct* str) { bool Resolver::ValidateStructure(const sem::Struct* str) {
auto name = builder_->Symbols().NameFor(str->Declaration()->name); auto name = builder_->Symbols().NameFor(str->Declaration()->name);
if (sem::ParseIntrinsicType(name) != sem::IntrinsicType::kNone) { if (sem::ParseBuiltinType(name) != sem::BuiltinType::kNone) {
AddError("'" + name + "' is a builtin and cannot be redeclared as a struct", AddError("'" + name + "' is a builtin and cannot be redeclared as a struct",
str->Declaration()->source); str->Declaration()->source);
return false; return false;

View File

@ -19,11 +19,11 @@
#include "src/ast/assignment_statement.h" #include "src/ast/assignment_statement.h"
#include "src/ast/bitcast_expression.h" #include "src/ast/bitcast_expression.h"
#include "src/ast/break_statement.h" #include "src/ast/break_statement.h"
#include "src/ast/builtin_texture_helper_test.h"
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/continue_statement.h" #include "src/ast/continue_statement.h"
#include "src/ast/discard_statement.h" #include "src/ast/discard_statement.h"
#include "src/ast/if_statement.h" #include "src/ast/if_statement.h"
#include "src/ast/intrinsic_texture_helper_test.h"
#include "src/ast/loop_statement.h" #include "src/ast/loop_statement.h"
#include "src/ast/return_statement.h" #include "src/ast/return_statement.h"
#include "src/ast/stage_attribute.h" #include "src/ast/stage_attribute.h"
@ -156,11 +156,11 @@ TEST_F(ResolverValidationTest, Expr_DontCall_Function) {
EXPECT_EQ(r()->error(), "3:8 error: missing '(' for function call"); EXPECT_EQ(r()->error(), "3:8 error: missing '(' for function call");
} }
TEST_F(ResolverValidationTest, Expr_DontCall_Intrinsic) { TEST_F(ResolverValidationTest, Expr_DontCall_Builtin) {
WrapInFunction(Expr(Source{{{3, 3}, {3, 8}}}, "round")); WrapInFunction(Expr(Source{{{3, 3}, {3, 8}}}, "round"));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "3:8 error: missing '(' for intrinsic call"); EXPECT_EQ(r()->error(), "3:8 error: missing '(' for builtin call");
} }
TEST_F(ResolverValidationTest, Expr_DontCall_Type) { TEST_F(ResolverValidationTest, Expr_DontCall_Type) {
@ -172,8 +172,7 @@ TEST_F(ResolverValidationTest, Expr_DontCall_Type) {
"3:8 error: missing '(' for type constructor or cast"); "3:8 error: missing '(' for type constructor or cast");
} }
TEST_F(ResolverValidationTest, TEST_F(ResolverValidationTest, AssignmentStmt_InvalidLHS_BuiltinFunctionName) {
AssignmentStmt_InvalidLHS_IntrinsicFunctionName) {
// normalize = 2; // normalize = 2;
auto* lhs = Expr(Source{{12, 34}}, "normalize"); auto* lhs = Expr(Source{{12, 34}}, "normalize");
@ -182,7 +181,7 @@ TEST_F(ResolverValidationTest,
WrapInFunction(assign); WrapInFunction(assign);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: missing '(' for intrinsic call"); EXPECT_EQ(r()->error(), "12:34 error: missing '(' for builtin call");
} }
TEST_F(ResolverValidationTest, UsingUndefinedVariable_Fail) { TEST_F(ResolverValidationTest, UsingUndefinedVariable_Fail) {

166
src/sem/builtin.cc Normal file
View File

@ -0,0 +1,166 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Doxygen seems to trip over this file for some unknown reason. Disable.
//! @cond Doxygen_Suppress
#include "src/sem/builtin.h"
#include <vector>
#include "src/utils/to_const_ptr_vec.h"
TINT_INSTANTIATE_TYPEINFO(tint::sem::Builtin);
namespace tint {
namespace sem {
const char* Builtin::str() const {
return sem::str(type_);
}
bool IsCoarseDerivativeBuiltin(BuiltinType i) {
return i == BuiltinType::kDpdxCoarse || i == BuiltinType::kDpdyCoarse ||
i == BuiltinType::kFwidthCoarse;
}
bool IsFineDerivativeBuiltin(BuiltinType i) {
return i == BuiltinType::kDpdxFine || i == BuiltinType::kDpdyFine ||
i == BuiltinType::kFwidthFine;
}
bool IsDerivativeBuiltin(BuiltinType i) {
return i == BuiltinType::kDpdx || i == BuiltinType::kDpdy ||
i == BuiltinType::kFwidth || IsCoarseDerivativeBuiltin(i) ||
IsFineDerivativeBuiltin(i);
}
bool IsFloatClassificationBuiltin(BuiltinType i) {
return i == BuiltinType::kIsFinite || i == BuiltinType::kIsInf ||
i == BuiltinType::kIsNan || i == BuiltinType::kIsNormal;
}
bool IsTextureBuiltin(BuiltinType i) {
return IsImageQueryBuiltin(i) || i == BuiltinType::kTextureLoad ||
i == BuiltinType::kTextureGather ||
i == BuiltinType::kTextureGatherCompare ||
i == BuiltinType::kTextureSample ||
i == BuiltinType::kTextureSampleLevel ||
i == BuiltinType::kTextureSampleBias ||
i == BuiltinType::kTextureSampleCompare ||
i == BuiltinType::kTextureSampleCompareLevel ||
i == BuiltinType::kTextureSampleGrad ||
i == BuiltinType::kTextureStore;
}
bool IsImageQueryBuiltin(BuiltinType i) {
return i == BuiltinType::kTextureDimensions ||
i == BuiltinType::kTextureNumLayers ||
i == BuiltinType::kTextureNumLevels ||
i == BuiltinType::kTextureNumSamples;
}
bool IsDataPackingBuiltin(BuiltinType i) {
return i == BuiltinType::kPack4x8snorm || i == BuiltinType::kPack4x8unorm ||
i == BuiltinType::kPack2x16snorm || i == BuiltinType::kPack2x16unorm ||
i == BuiltinType::kPack2x16float;
}
bool IsDataUnpackingBuiltin(BuiltinType i) {
return i == BuiltinType::kUnpack4x8snorm ||
i == BuiltinType::kUnpack4x8unorm ||
i == BuiltinType::kUnpack2x16snorm ||
i == BuiltinType::kUnpack2x16unorm ||
i == BuiltinType::kUnpack2x16float;
}
bool IsBarrierBuiltin(BuiltinType i) {
return i == BuiltinType::kWorkgroupBarrier ||
i == BuiltinType::kStorageBarrier;
}
bool IsAtomicBuiltin(BuiltinType i) {
return i == sem::BuiltinType::kAtomicLoad ||
i == sem::BuiltinType::kAtomicStore ||
i == sem::BuiltinType::kAtomicAdd ||
i == sem::BuiltinType::kAtomicSub ||
i == sem::BuiltinType::kAtomicMax ||
i == sem::BuiltinType::kAtomicMin ||
i == sem::BuiltinType::kAtomicAnd ||
i == sem::BuiltinType::kAtomicOr ||
i == sem::BuiltinType::kAtomicXor ||
i == sem::BuiltinType::kAtomicExchange ||
i == sem::BuiltinType::kAtomicCompareExchangeWeak;
}
Builtin::Builtin(BuiltinType type,
const sem::Type* return_type,
std::vector<Parameter*> parameters,
PipelineStageSet supported_stages,
bool is_deprecated)
: Base(return_type, utils::ToConstPtrVec(parameters)),
type_(type),
supported_stages_(supported_stages),
is_deprecated_(is_deprecated) {
for (auto* parameter : parameters) {
parameter->SetOwner(this);
}
}
Builtin::~Builtin() = default;
bool Builtin::IsCoarseDerivative() const {
return IsCoarseDerivativeBuiltin(type_);
}
bool Builtin::IsFineDerivative() const {
return IsFineDerivativeBuiltin(type_);
}
bool Builtin::IsDerivative() const {
return IsDerivativeBuiltin(type_);
}
bool Builtin::IsFloatClassification() const {
return IsFloatClassificationBuiltin(type_);
}
bool Builtin::IsTexture() const {
return IsTextureBuiltin(type_);
}
bool Builtin::IsImageQuery() const {
return IsImageQueryBuiltin(type_);
}
bool Builtin::IsDataPacking() const {
return IsDataPackingBuiltin(type_);
}
bool Builtin::IsDataUnpacking() const {
return IsDataUnpackingBuiltin(type_);
}
bool Builtin::IsBarrier() const {
return IsBarrierBuiltin(type_);
}
bool Builtin::IsAtomic() const {
return IsAtomicBuiltin(type_);
}
} // namespace sem
} // namespace tint
//! @endcond

173
src/sem/builtin.h Normal file
View File

@ -0,0 +1,173 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_SEM_BUILTIN_H_
#define SRC_SEM_BUILTIN_H_
#include <string>
#include <vector>
#include "src/sem/builtin_type.h"
#include "src/sem/call_target.h"
#include "src/sem/pipeline_stage_set.h"
#include "src/utils/hash.h"
namespace tint {
namespace sem {
/// Determines if the given `i` is a coarse derivative
/// @param i the builtin type
/// @returns true if the given derivative is coarse.
bool IsCoarseDerivativeBuiltin(BuiltinType i);
/// Determines if the given `i` is a fine derivative
/// @param i the builtin type
/// @returns true if the given derivative is fine.
bool IsFineDerivativeBuiltin(BuiltinType i);
/// Determine if the given `i` is a derivative builtin
/// @param i the builtin type
/// @returns true if the given `i` is a derivative builtin
bool IsDerivativeBuiltin(BuiltinType i);
/// Determines if the given `i` is a float classification builtin
/// @param i the builtin type
/// @returns true if the given `i` is a float builtin
bool IsFloatClassificationBuiltin(BuiltinType i);
/// Determines if the given `i` is a texture operation builtin
/// @param i the builtin type
/// @returns true if the given `i` is a texture operation builtin
bool IsTextureBuiltin(BuiltinType i);
/// Determines if the given `i` is a image query builtin
/// @param i the builtin type
/// @returns true if the given `i` is a image query builtin
bool IsImageQueryBuiltin(BuiltinType i);
/// Determines if the given `i` is a data packing builtin
/// @param i the builtin
/// @returns true if the given `i` is a data packing builtin
bool IsDataPackingBuiltin(BuiltinType i);
/// Determines if the given `i` is a data unpacking builtin
/// @param i the builtin
/// @returns true if the given `i` is a data unpacking builtin
bool IsDataUnpackingBuiltin(BuiltinType i);
/// Determines if the given `i` is a barrier builtin
/// @param i the builtin
/// @returns true if the given `i` is a barrier builtin
bool IsBarrierBuiltin(BuiltinType i);
/// Determines if the given `i` is a atomic builtin
/// @param i the builtin
/// @returns true if the given `i` is a atomic builtin
bool IsAtomicBuiltin(BuiltinType i);
/// Builtin holds the semantic information for a builtin function.
class Builtin : public Castable<Builtin, CallTarget> {
public:
/// Constructor
/// @param type the builtin type
/// @param return_type the return type for the builtin call
/// @param parameters the parameters for the builtin overload
/// @param supported_stages the pipeline stages that this builtin can be
/// used in
/// @param is_deprecated true if the particular overload is considered
/// deprecated
Builtin(BuiltinType type,
const sem::Type* return_type,
std::vector<Parameter*> parameters,
PipelineStageSet supported_stages,
bool is_deprecated);
/// Destructor
~Builtin() override;
/// @return the type of the builtin
BuiltinType Type() const { return type_; }
/// @return the pipeline stages that this builtin can be used in
PipelineStageSet SupportedStages() const { return supported_stages_; }
/// @return true if the builtin overload is considered deprecated
bool IsDeprecated() const { return is_deprecated_; }
/// @returns the name of the builtin function type. The spelling, including
/// case, matches the name in the WGSL spec.
const char* str() const;
/// @returns true if builtin is a coarse derivative builtin
bool IsCoarseDerivative() const;
/// @returns true if builtin is a fine a derivative builtin
bool IsFineDerivative() const;
/// @returns true if builtin is a derivative builtin
bool IsDerivative() const;
/// @returns true if builtin is a float builtin
bool IsFloatClassification() const;
/// @returns true if builtin is a texture operation builtin
bool IsTexture() const;
/// @returns true if builtin is a image query builtin
bool IsImageQuery() const;
/// @returns true if builtin is a data packing builtin
bool IsDataPacking() const;
/// @returns true if builtin is a data unpacking builtin
bool IsDataUnpacking() const;
/// @returns true if builtin is a barrier builtin
bool IsBarrier() const;
/// @returns true if builtin is a atomic builtin
bool IsAtomic() const;
private:
const BuiltinType type_;
const PipelineStageSet supported_stages_;
const bool is_deprecated_;
};
/// Constant value used by the degrees() builtin
static constexpr double kRadToDeg = 57.295779513082322865;
/// Constant value used by the radians() builtin
static constexpr double kDegToRad = 0.017453292519943295474;
} // namespace sem
} // namespace tint
namespace std {
/// Custom std::hash specialization for tint::sem::Builtin
template <>
class hash<tint::sem::Builtin> {
public:
/// @param i the Builtin to create a hash for
/// @return the hash value
inline std::size_t operator()(const tint::sem::Builtin& i) const {
return tint::utils::Hash(i.Type(), i.SupportedStages(), i.ReturnType(),
i.Parameters(), i.IsDeprecated());
}
};
} // namespace std
#endif // SRC_SEM_BUILTIN_H_

131
src/sem/builtin_test.cc Normal file
View File

@ -0,0 +1,131 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/sem/builtin.h"
#include "gtest/gtest.h"
namespace tint {
namespace sem {
namespace {
struct BuiltinData {
const char* name;
BuiltinType builtin;
};
inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
out << data.name;
return out;
}
using BuiltinTypeTest = testing::TestWithParam<BuiltinData>;
TEST_P(BuiltinTypeTest, Parse) {
auto param = GetParam();
EXPECT_EQ(ParseBuiltinType(param.name), param.builtin);
}
INSTANTIATE_TEST_SUITE_P(
BuiltinTypeTest,
BuiltinTypeTest,
testing::Values(
BuiltinData{"abs", BuiltinType::kAbs},
BuiltinData{"acos", BuiltinType::kAcos},
BuiltinData{"all", BuiltinType::kAll},
BuiltinData{"any", BuiltinType::kAny},
BuiltinData{"arrayLength", BuiltinType::kArrayLength},
BuiltinData{"asin", BuiltinType::kAsin},
BuiltinData{"atan", BuiltinType::kAtan},
BuiltinData{"atan2", BuiltinType::kAtan2},
BuiltinData{"ceil", BuiltinType::kCeil},
BuiltinData{"clamp", BuiltinType::kClamp},
BuiltinData{"cos", BuiltinType::kCos},
BuiltinData{"cosh", BuiltinType::kCosh},
BuiltinData{"countOneBits", BuiltinType::kCountOneBits},
BuiltinData{"cross", BuiltinType::kCross},
BuiltinData{"determinant", BuiltinType::kDeterminant},
BuiltinData{"distance", BuiltinType::kDistance},
BuiltinData{"dot", BuiltinType::kDot},
BuiltinData{"dpdx", BuiltinType::kDpdx},
BuiltinData{"dpdxCoarse", BuiltinType::kDpdxCoarse},
BuiltinData{"dpdxFine", BuiltinType::kDpdxFine},
BuiltinData{"dpdy", BuiltinType::kDpdy},
BuiltinData{"dpdyCoarse", BuiltinType::kDpdyCoarse},
BuiltinData{"dpdyFine", BuiltinType::kDpdyFine},
BuiltinData{"exp", BuiltinType::kExp},
BuiltinData{"exp2", BuiltinType::kExp2},
BuiltinData{"faceForward", BuiltinType::kFaceForward},
BuiltinData{"floor", BuiltinType::kFloor},
BuiltinData{"fma", BuiltinType::kFma},
BuiltinData{"fract", BuiltinType::kFract},
BuiltinData{"frexp", BuiltinType::kFrexp},
BuiltinData{"fwidth", BuiltinType::kFwidth},
BuiltinData{"fwidthCoarse", BuiltinType::kFwidthCoarse},
BuiltinData{"fwidthFine", BuiltinType::kFwidthFine},
BuiltinData{"inverseSqrt", BuiltinType::kInverseSqrt},
BuiltinData{"isFinite", BuiltinType::kIsFinite},
BuiltinData{"isInf", BuiltinType::kIsInf},
BuiltinData{"isNan", BuiltinType::kIsNan},
BuiltinData{"isNormal", BuiltinType::kIsNormal},
BuiltinData{"ldexp", BuiltinType::kLdexp},
BuiltinData{"length", BuiltinType::kLength},
BuiltinData{"log", BuiltinType::kLog},
BuiltinData{"log2", BuiltinType::kLog2},
BuiltinData{"max", BuiltinType::kMax},
BuiltinData{"min", BuiltinType::kMin},
BuiltinData{"mix", BuiltinType::kMix},
BuiltinData{"modf", BuiltinType::kModf},
BuiltinData{"normalize", BuiltinType::kNormalize},
BuiltinData{"pow", BuiltinType::kPow},
BuiltinData{"reflect", BuiltinType::kReflect},
BuiltinData{"reverseBits", BuiltinType::kReverseBits},
BuiltinData{"round", BuiltinType::kRound},
BuiltinData{"select", BuiltinType::kSelect},
BuiltinData{"sign", BuiltinType::kSign},
BuiltinData{"sin", BuiltinType::kSin},
BuiltinData{"sinh", BuiltinType::kSinh},
BuiltinData{"smoothStep", BuiltinType::kSmoothStep},
BuiltinData{"sqrt", BuiltinType::kSqrt},
BuiltinData{"step", BuiltinType::kStep},
BuiltinData{"storageBarrier", BuiltinType::kStorageBarrier},
BuiltinData{"tan", BuiltinType::kTan},
BuiltinData{"tanh", BuiltinType::kTanh},
BuiltinData{"textureDimensions", BuiltinType::kTextureDimensions},
BuiltinData{"textureLoad", BuiltinType::kTextureLoad},
BuiltinData{"textureNumLayers", BuiltinType::kTextureNumLayers},
BuiltinData{"textureNumLevels", BuiltinType::kTextureNumLevels},
BuiltinData{"textureNumSamples", BuiltinType::kTextureNumSamples},
BuiltinData{"textureSample", BuiltinType::kTextureSample},
BuiltinData{"textureSampleBias", BuiltinType::kTextureSampleBias},
BuiltinData{"textureSampleCompare", BuiltinType::kTextureSampleCompare},
BuiltinData{"textureSampleCompareLevel",
BuiltinType::kTextureSampleCompareLevel},
BuiltinData{"textureSampleGrad", BuiltinType::kTextureSampleGrad},
BuiltinData{"textureSampleLevel", BuiltinType::kTextureSampleLevel},
BuiltinData{"trunc", BuiltinType::kTrunc},
BuiltinData{"unpack2x16float", BuiltinType::kUnpack2x16float},
BuiltinData{"unpack2x16snorm", BuiltinType::kUnpack2x16snorm},
BuiltinData{"unpack2x16unorm", BuiltinType::kUnpack2x16unorm},
BuiltinData{"unpack4x8snorm", BuiltinType::kUnpack4x8snorm},
BuiltinData{"unpack4x8unorm", BuiltinType::kUnpack4x8unorm},
BuiltinData{"workgroupBarrier", BuiltinType::kWorkgroupBarrier}));
TEST_F(BuiltinTypeTest, ParseNoMatch) {
EXPECT_EQ(ParseBuiltinType("not_builtin"), BuiltinType::kNone);
}
} // namespace
} // namespace sem
} // namespace tint

560
src/sem/builtin_type.cc Normal file
View File

@ -0,0 +1,560 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/builtin-gen
// using the template:
// src/sem/builtin_type.cc.tmpl
// and the builtin defintion file:
// src/builtins.def
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#include "src/sem/builtin_type.h"
#include <sstream>
namespace tint {
namespace sem {
BuiltinType ParseBuiltinType(const std::string& name) {
if (name == "abs") {
return BuiltinType::kAbs;
}
if (name == "acos") {
return BuiltinType::kAcos;
}
if (name == "all") {
return BuiltinType::kAll;
}
if (name == "any") {
return BuiltinType::kAny;
}
if (name == "arrayLength") {
return BuiltinType::kArrayLength;
}
if (name == "asin") {
return BuiltinType::kAsin;
}
if (name == "atan") {
return BuiltinType::kAtan;
}
if (name == "atan2") {
return BuiltinType::kAtan2;
}
if (name == "ceil") {
return BuiltinType::kCeil;
}
if (name == "clamp") {
return BuiltinType::kClamp;
}
if (name == "cos") {
return BuiltinType::kCos;
}
if (name == "cosh") {
return BuiltinType::kCosh;
}
if (name == "countOneBits") {
return BuiltinType::kCountOneBits;
}
if (name == "cross") {
return BuiltinType::kCross;
}
if (name == "degrees") {
return BuiltinType::kDegrees;
}
if (name == "determinant") {
return BuiltinType::kDeterminant;
}
if (name == "distance") {
return BuiltinType::kDistance;
}
if (name == "dot") {
return BuiltinType::kDot;
}
if (name == "dpdx") {
return BuiltinType::kDpdx;
}
if (name == "dpdxCoarse") {
return BuiltinType::kDpdxCoarse;
}
if (name == "dpdxFine") {
return BuiltinType::kDpdxFine;
}
if (name == "dpdy") {
return BuiltinType::kDpdy;
}
if (name == "dpdyCoarse") {
return BuiltinType::kDpdyCoarse;
}
if (name == "dpdyFine") {
return BuiltinType::kDpdyFine;
}
if (name == "exp") {
return BuiltinType::kExp;
}
if (name == "exp2") {
return BuiltinType::kExp2;
}
if (name == "faceForward") {
return BuiltinType::kFaceForward;
}
if (name == "floor") {
return BuiltinType::kFloor;
}
if (name == "fma") {
return BuiltinType::kFma;
}
if (name == "fract") {
return BuiltinType::kFract;
}
if (name == "frexp") {
return BuiltinType::kFrexp;
}
if (name == "fwidth") {
return BuiltinType::kFwidth;
}
if (name == "fwidthCoarse") {
return BuiltinType::kFwidthCoarse;
}
if (name == "fwidthFine") {
return BuiltinType::kFwidthFine;
}
if (name == "inverseSqrt") {
return BuiltinType::kInverseSqrt;
}
if (name == "isFinite") {
return BuiltinType::kIsFinite;
}
if (name == "isInf") {
return BuiltinType::kIsInf;
}
if (name == "isNan") {
return BuiltinType::kIsNan;
}
if (name == "isNormal") {
return BuiltinType::kIsNormal;
}
if (name == "ldexp") {
return BuiltinType::kLdexp;
}
if (name == "length") {
return BuiltinType::kLength;
}
if (name == "log") {
return BuiltinType::kLog;
}
if (name == "log2") {
return BuiltinType::kLog2;
}
if (name == "max") {
return BuiltinType::kMax;
}
if (name == "min") {
return BuiltinType::kMin;
}
if (name == "mix") {
return BuiltinType::kMix;
}
if (name == "modf") {
return BuiltinType::kModf;
}
if (name == "normalize") {
return BuiltinType::kNormalize;
}
if (name == "pack2x16float") {
return BuiltinType::kPack2x16float;
}
if (name == "pack2x16snorm") {
return BuiltinType::kPack2x16snorm;
}
if (name == "pack2x16unorm") {
return BuiltinType::kPack2x16unorm;
}
if (name == "pack4x8snorm") {
return BuiltinType::kPack4x8snorm;
}
if (name == "pack4x8unorm") {
return BuiltinType::kPack4x8unorm;
}
if (name == "pow") {
return BuiltinType::kPow;
}
if (name == "radians") {
return BuiltinType::kRadians;
}
if (name == "reflect") {
return BuiltinType::kReflect;
}
if (name == "refract") {
return BuiltinType::kRefract;
}
if (name == "reverseBits") {
return BuiltinType::kReverseBits;
}
if (name == "round") {
return BuiltinType::kRound;
}
if (name == "select") {
return BuiltinType::kSelect;
}
if (name == "sign") {
return BuiltinType::kSign;
}
if (name == "sin") {
return BuiltinType::kSin;
}
if (name == "sinh") {
return BuiltinType::kSinh;
}
if (name == "smoothStep") {
return BuiltinType::kSmoothStep;
}
if (name == "sqrt") {
return BuiltinType::kSqrt;
}
if (name == "step") {
return BuiltinType::kStep;
}
if (name == "storageBarrier") {
return BuiltinType::kStorageBarrier;
}
if (name == "tan") {
return BuiltinType::kTan;
}
if (name == "tanh") {
return BuiltinType::kTanh;
}
if (name == "transpose") {
return BuiltinType::kTranspose;
}
if (name == "trunc") {
return BuiltinType::kTrunc;
}
if (name == "unpack2x16float") {
return BuiltinType::kUnpack2x16float;
}
if (name == "unpack2x16snorm") {
return BuiltinType::kUnpack2x16snorm;
}
if (name == "unpack2x16unorm") {
return BuiltinType::kUnpack2x16unorm;
}
if (name == "unpack4x8snorm") {
return BuiltinType::kUnpack4x8snorm;
}
if (name == "unpack4x8unorm") {
return BuiltinType::kUnpack4x8unorm;
}
if (name == "workgroupBarrier") {
return BuiltinType::kWorkgroupBarrier;
}
if (name == "textureDimensions") {
return BuiltinType::kTextureDimensions;
}
if (name == "textureGather") {
return BuiltinType::kTextureGather;
}
if (name == "textureGatherCompare") {
return BuiltinType::kTextureGatherCompare;
}
if (name == "textureNumLayers") {
return BuiltinType::kTextureNumLayers;
}
if (name == "textureNumLevels") {
return BuiltinType::kTextureNumLevels;
}
if (name == "textureNumSamples") {
return BuiltinType::kTextureNumSamples;
}
if (name == "textureSample") {
return BuiltinType::kTextureSample;
}
if (name == "textureSampleBias") {
return BuiltinType::kTextureSampleBias;
}
if (name == "textureSampleCompare") {
return BuiltinType::kTextureSampleCompare;
}
if (name == "textureSampleCompareLevel") {
return BuiltinType::kTextureSampleCompareLevel;
}
if (name == "textureSampleGrad") {
return BuiltinType::kTextureSampleGrad;
}
if (name == "textureSampleLevel") {
return BuiltinType::kTextureSampleLevel;
}
if (name == "textureStore") {
return BuiltinType::kTextureStore;
}
if (name == "textureLoad") {
return BuiltinType::kTextureLoad;
}
if (name == "atomicLoad") {
return BuiltinType::kAtomicLoad;
}
if (name == "atomicStore") {
return BuiltinType::kAtomicStore;
}
if (name == "atomicAdd") {
return BuiltinType::kAtomicAdd;
}
if (name == "atomicSub") {
return BuiltinType::kAtomicSub;
}
if (name == "atomicMax") {
return BuiltinType::kAtomicMax;
}
if (name == "atomicMin") {
return BuiltinType::kAtomicMin;
}
if (name == "atomicAnd") {
return BuiltinType::kAtomicAnd;
}
if (name == "atomicOr") {
return BuiltinType::kAtomicOr;
}
if (name == "atomicXor") {
return BuiltinType::kAtomicXor;
}
if (name == "atomicExchange") {
return BuiltinType::kAtomicExchange;
}
if (name == "atomicCompareExchangeWeak") {
return BuiltinType::kAtomicCompareExchangeWeak;
}
return BuiltinType::kNone;
}
const char* str(BuiltinType i) {
switch (i) {
case BuiltinType::kNone:
return "<none>";
case BuiltinType::kAbs:
return "abs";
case BuiltinType::kAcos:
return "acos";
case BuiltinType::kAll:
return "all";
case BuiltinType::kAny:
return "any";
case BuiltinType::kArrayLength:
return "arrayLength";
case BuiltinType::kAsin:
return "asin";
case BuiltinType::kAtan:
return "atan";
case BuiltinType::kAtan2:
return "atan2";
case BuiltinType::kCeil:
return "ceil";
case BuiltinType::kClamp:
return "clamp";
case BuiltinType::kCos:
return "cos";
case BuiltinType::kCosh:
return "cosh";
case BuiltinType::kCountOneBits:
return "countOneBits";
case BuiltinType::kCross:
return "cross";
case BuiltinType::kDegrees:
return "degrees";
case BuiltinType::kDeterminant:
return "determinant";
case BuiltinType::kDistance:
return "distance";
case BuiltinType::kDot:
return "dot";
case BuiltinType::kDpdx:
return "dpdx";
case BuiltinType::kDpdxCoarse:
return "dpdxCoarse";
case BuiltinType::kDpdxFine:
return "dpdxFine";
case BuiltinType::kDpdy:
return "dpdy";
case BuiltinType::kDpdyCoarse:
return "dpdyCoarse";
case BuiltinType::kDpdyFine:
return "dpdyFine";
case BuiltinType::kExp:
return "exp";
case BuiltinType::kExp2:
return "exp2";
case BuiltinType::kFaceForward:
return "faceForward";
case BuiltinType::kFloor:
return "floor";
case BuiltinType::kFma:
return "fma";
case BuiltinType::kFract:
return "fract";
case BuiltinType::kFrexp:
return "frexp";
case BuiltinType::kFwidth:
return "fwidth";
case BuiltinType::kFwidthCoarse:
return "fwidthCoarse";
case BuiltinType::kFwidthFine:
return "fwidthFine";
case BuiltinType::kInverseSqrt:
return "inverseSqrt";
case BuiltinType::kIsFinite:
return "isFinite";
case BuiltinType::kIsInf:
return "isInf";
case BuiltinType::kIsNan:
return "isNan";
case BuiltinType::kIsNormal:
return "isNormal";
case BuiltinType::kLdexp:
return "ldexp";
case BuiltinType::kLength:
return "length";
case BuiltinType::kLog:
return "log";
case BuiltinType::kLog2:
return "log2";
case BuiltinType::kMax:
return "max";
case BuiltinType::kMin:
return "min";
case BuiltinType::kMix:
return "mix";
case BuiltinType::kModf:
return "modf";
case BuiltinType::kNormalize:
return "normalize";
case BuiltinType::kPack2x16float:
return "pack2x16float";
case BuiltinType::kPack2x16snorm:
return "pack2x16snorm";
case BuiltinType::kPack2x16unorm:
return "pack2x16unorm";
case BuiltinType::kPack4x8snorm:
return "pack4x8snorm";
case BuiltinType::kPack4x8unorm:
return "pack4x8unorm";
case BuiltinType::kPow:
return "pow";
case BuiltinType::kRadians:
return "radians";
case BuiltinType::kReflect:
return "reflect";
case BuiltinType::kRefract:
return "refract";
case BuiltinType::kReverseBits:
return "reverseBits";
case BuiltinType::kRound:
return "round";
case BuiltinType::kSelect:
return "select";
case BuiltinType::kSign:
return "sign";
case BuiltinType::kSin:
return "sin";
case BuiltinType::kSinh:
return "sinh";
case BuiltinType::kSmoothStep:
return "smoothStep";
case BuiltinType::kSqrt:
return "sqrt";
case BuiltinType::kStep:
return "step";
case BuiltinType::kStorageBarrier:
return "storageBarrier";
case BuiltinType::kTan:
return "tan";
case BuiltinType::kTanh:
return "tanh";
case BuiltinType::kTranspose:
return "transpose";
case BuiltinType::kTrunc:
return "trunc";
case BuiltinType::kUnpack2x16float:
return "unpack2x16float";
case BuiltinType::kUnpack2x16snorm:
return "unpack2x16snorm";
case BuiltinType::kUnpack2x16unorm:
return "unpack2x16unorm";
case BuiltinType::kUnpack4x8snorm:
return "unpack4x8snorm";
case BuiltinType::kUnpack4x8unorm:
return "unpack4x8unorm";
case BuiltinType::kWorkgroupBarrier:
return "workgroupBarrier";
case BuiltinType::kTextureDimensions:
return "textureDimensions";
case BuiltinType::kTextureGather:
return "textureGather";
case BuiltinType::kTextureGatherCompare:
return "textureGatherCompare";
case BuiltinType::kTextureNumLayers:
return "textureNumLayers";
case BuiltinType::kTextureNumLevels:
return "textureNumLevels";
case BuiltinType::kTextureNumSamples:
return "textureNumSamples";
case BuiltinType::kTextureSample:
return "textureSample";
case BuiltinType::kTextureSampleBias:
return "textureSampleBias";
case BuiltinType::kTextureSampleCompare:
return "textureSampleCompare";
case BuiltinType::kTextureSampleCompareLevel:
return "textureSampleCompareLevel";
case BuiltinType::kTextureSampleGrad:
return "textureSampleGrad";
case BuiltinType::kTextureSampleLevel:
return "textureSampleLevel";
case BuiltinType::kTextureStore:
return "textureStore";
case BuiltinType::kTextureLoad:
return "textureLoad";
case BuiltinType::kAtomicLoad:
return "atomicLoad";
case BuiltinType::kAtomicStore:
return "atomicStore";
case BuiltinType::kAtomicAdd:
return "atomicAdd";
case BuiltinType::kAtomicSub:
return "atomicSub";
case BuiltinType::kAtomicMax:
return "atomicMax";
case BuiltinType::kAtomicMin:
return "atomicMin";
case BuiltinType::kAtomicAnd:
return "atomicAnd";
case BuiltinType::kAtomicOr:
return "atomicOr";
case BuiltinType::kAtomicXor:
return "atomicXor";
case BuiltinType::kAtomicExchange:
return "atomicExchange";
case BuiltinType::kAtomicCompareExchangeWeak:
return "atomicCompareExchangeWeak";
}
return "<unknown>";
}
std::ostream& operator<<(std::ostream& out, BuiltinType i) {
out << str(i);
return out;
}
} // namespace sem
} // namespace tint

View File

@ -1,42 +1,42 @@
{{- /* {{- /*
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Template file for use with tools/intrinsic-gen to generate intrinsic_type.cc Template file for use with tools/builtin-gen to generate builtin_type.cc
See: See:
* tools/cmd/intrinsic-gen/gen for structures used by this template * tools/cmd/builtin-gen/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax * https://golang.org/pkg/text/template/ for documentation on the template syntax
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
*/ -}} */ -}}
#include "src/sem/intrinsic_type.h" #include "src/sem/builtin_type.h"
#include <sstream> #include <sstream>
namespace tint { namespace tint {
namespace sem { namespace sem {
IntrinsicType ParseIntrinsicType(const std::string& name) { BuiltinType ParseBuiltinType(const std::string& name) {
{{- range .Sem.Functions }} {{- range .Sem.Functions }}
if (name == "{{.Name}}") { if (name == "{{.Name}}") {
return IntrinsicType::k{{Title .Name}}; return BuiltinType::k{{Title .Name}};
} }
{{- end }} {{- end }}
return IntrinsicType::kNone; return BuiltinType::kNone;
} }
const char* str(IntrinsicType i) { const char* str(BuiltinType i) {
switch (i) { switch (i) {
case IntrinsicType::kNone: case BuiltinType::kNone:
return "<none>"; return "<none>";
{{- range .Sem.Functions }} {{- range .Sem.Functions }}
case IntrinsicType::k{{Title .Name}}: case BuiltinType::k{{Title .Name}}:
return "{{.Name}}"; return "{{.Name}}";
{{- end }} {{- end }}
} }
return "<unknown>"; return "<unknown>";
} }
std::ostream& operator<<(std::ostream& out, IntrinsicType i) { std::ostream& operator<<(std::ostream& out, BuiltinType i) {
out << str(i); out << str(i);
return out; return out;
} }

View File

@ -13,17 +13,17 @@
// limitations under the License. // limitations under the License.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen // File generated by tools/builtin-gen
// using the template: // using the template:
// src/sem/intrinsic_type.h.tmpl // src/sem/builtin_type.h.tmpl
// and the intrinsic defintion file: // and the builtin defintion file:
// src/intrinsics.def // src/builtins.def
// //
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifndef SRC_SEM_INTRINSIC_TYPE_H_ #ifndef SRC_SEM_BUILTIN_TYPE_H_
#define SRC_SEM_INTRINSIC_TYPE_H_ #define SRC_SEM_BUILTIN_TYPE_H_
#include <sstream> #include <sstream>
#include <string> #include <string>
@ -31,8 +31,8 @@
namespace tint { namespace tint {
namespace sem { namespace sem {
/// Enumerator of all intrinsic functions /// Enumerator of all builtin functions
enum class IntrinsicType { enum class BuiltinType {
kNone = -1, kNone = -1,
kAbs, kAbs,
kAcos, kAcos,
@ -138,21 +138,21 @@ enum class IntrinsicType {
kAtomicCompareExchangeWeak, kAtomicCompareExchangeWeak,
}; };
/// Matches the IntrinsicType by name /// Matches the BuiltinType by name
/// @param name the intrinsic name to parse /// @param name the builtin name to parse
/// @returns the parsed IntrinsicType, or IntrinsicType::kNone if `name` did not /// @returns the parsed BuiltinType, or BuiltinType::kNone if `name` did not
/// match any intrinsic. /// match any builtin.
IntrinsicType ParseIntrinsicType(const std::string& name); BuiltinType ParseBuiltinType(const std::string& name);
/// @returns the name of the intrinsic function type. The spelling, including /// @returns the name of the builtin function type. The spelling, including
/// case, matches the name in the WGSL spec. /// case, matches the name in the WGSL spec.
const char* str(IntrinsicType i); const char* str(BuiltinType i);
/// Emits the name of the intrinsic function type. The spelling, including case, /// Emits the name of the builtin function type. The spelling, including case,
/// matches the name in the WGSL spec. /// matches the name in the WGSL spec.
std::ostream& operator<<(std::ostream& out, IntrinsicType i); std::ostream& operator<<(std::ostream& out, BuiltinType i);
} // namespace sem } // namespace sem
} // namespace tint } // namespace tint
#endif // SRC_SEM_INTRINSIC_TYPE_H_ #endif // SRC_SEM_BUILTIN_TYPE_H_

View File

@ -0,0 +1,45 @@
{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/builtin-gen to generate builtin_type.h
See:
* tools/cmd/builtin-gen/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}
#ifndef SRC_SEM_BUILTIN_TYPE_H_
#define SRC_SEM_BUILTIN_TYPE_H_
#include <sstream>
#include <string>
namespace tint {
namespace sem {
/// Enumerator of all builtin functions
enum class BuiltinType {
kNone = -1,
{{- range .Sem.Functions }}
k{{Title .Name}},
{{- end }}
};
/// Matches the BuiltinType by name
/// @param name the builtin name to parse
/// @returns the parsed BuiltinType, or BuiltinType::kNone if `name` did not
/// match any builtin.
BuiltinType ParseBuiltinType(const std::string& name);
/// @returns the name of the builtin function type. The spelling, including
/// case, matches the name in the WGSL spec.
const char* str(BuiltinType i);
/// Emits the name of the builtin function type. The spelling, including case,
/// matches the name in the WGSL spec.
std::ostream& operator<<(std::ostream& out, BuiltinType i);
} // namespace sem
} // namespace tint
#endif // SRC_SEM_BUILTIN_TYPE_H_

View File

@ -17,8 +17,8 @@
#include <vector> #include <vector>
#include "src/sem/builtin.h"
#include "src/sem/expression.h" #include "src/sem/expression.h"
#include "src/sem/intrinsic.h"
namespace tint { namespace tint {
namespace sem { namespace sem {

View File

@ -56,7 +56,7 @@ struct CallTargetSignature {
int IndexOf(ParameterUsage usage) const; int IndexOf(ParameterUsage usage) const;
}; };
/// CallTarget is the base for callable functions, intrinsics, type constructors /// CallTarget is the base for callable functions, builtins, type constructors
/// and type casts. /// and type casts.
class CallTarget : public Castable<CallTarget, Node> { class CallTarget : public Castable<CallTarget, Node> {
public: public:

View File

@ -35,7 +35,7 @@ class ReturnStatement;
namespace sem { namespace sem {
class Intrinsic; class Builtin;
class Variable; class Variable;
/// WorkgroupDimension describes the size of a single dimension of an entry /// WorkgroupDimension describes the size of a single dimension of an entry
@ -120,16 +120,15 @@ class Function : public Castable<Function, CallTarget> {
transitively_called_functions_.add(function); transitively_called_functions_.add(function);
} }
/// @returns the list of intrinsics that this function directly calls. /// @returns the list of builtins that this function directly calls.
const utils::UniqueVector<const Intrinsic*>& DirectlyCalledIntrinsics() const utils::UniqueVector<const Builtin*>& DirectlyCalledBuiltins() const {
const { return directly_called_builtins_;
return directly_called_intrinsics_;
} }
/// Records that this function transitively calls `intrinsic`. /// Records that this function transitively calls `builtin`.
/// @param intrinsic the intrinsic this function directly calls /// @param builtin the builtin this function directly calls
void AddDirectlyCalledIntrinsic(const Intrinsic* intrinsic) { void AddDirectlyCalledBuiltin(const Builtin* builtin) {
directly_called_intrinsics_.add(intrinsic); directly_called_builtins_.add(builtin);
} }
/// Adds the given texture/sampler pair to the list of unique pairs /// Adds the given texture/sampler pair to the list of unique pairs
@ -149,13 +148,13 @@ class Function : public Castable<Function, CallTarget> {
return texture_sampler_pairs_; return texture_sampler_pairs_;
} }
/// @returns the list of direct calls to functions / intrinsics made by this /// @returns the list of direct calls to functions / builtins made by this
/// function /// function
std::vector<const Call*> DirectCallStatements() const { std::vector<const Call*> DirectCallStatements() const {
return direct_calls_; return direct_calls_;
} }
/// Adds a record of the direct function / intrinsic calls made by this /// Adds a record of the direct function / builtin calls made by this
/// function /// function
/// @param call the call /// @param call the call
void AddDirectCall(const Call* call) { direct_calls_.emplace_back(call); } void AddDirectCall(const Call* call) { direct_calls_.emplace_back(call); }
@ -275,7 +274,7 @@ class Function : public Castable<Function, CallTarget> {
utils::UniqueVector<const GlobalVariable*> directly_referenced_globals_; utils::UniqueVector<const GlobalVariable*> directly_referenced_globals_;
utils::UniqueVector<const GlobalVariable*> transitively_referenced_globals_; utils::UniqueVector<const GlobalVariable*> transitively_referenced_globals_;
utils::UniqueVector<const Function*> transitively_called_functions_; utils::UniqueVector<const Function*> transitively_called_functions_;
utils::UniqueVector<const Intrinsic*> directly_called_intrinsics_; utils::UniqueVector<const Builtin*> directly_called_builtins_;
utils::UniqueVector<VariablePair> texture_sampler_pairs_; utils::UniqueVector<VariablePair> texture_sampler_pairs_;
std::vector<const Call*> direct_calls_; std::vector<const Call*> direct_calls_;
std::vector<const Call*> callsites_; std::vector<const Call*> callsites_;

View File

@ -1,163 +0,0 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/sem/intrinsic.h"
#include <vector>
#include "src/utils/to_const_ptr_vec.h"
TINT_INSTANTIATE_TYPEINFO(tint::sem::Intrinsic);
namespace tint {
namespace sem {
const char* Intrinsic::str() const {
return sem::str(type_);
}
bool IsCoarseDerivativeIntrinsic(IntrinsicType i) {
return i == IntrinsicType::kDpdxCoarse || i == IntrinsicType::kDpdyCoarse ||
i == IntrinsicType::kFwidthCoarse;
}
bool IsFineDerivativeIntrinsic(IntrinsicType i) {
return i == IntrinsicType::kDpdxFine || i == IntrinsicType::kDpdyFine ||
i == IntrinsicType::kFwidthFine;
}
bool IsDerivativeIntrinsic(IntrinsicType i) {
return i == IntrinsicType::kDpdx || i == IntrinsicType::kDpdy ||
i == IntrinsicType::kFwidth || IsCoarseDerivativeIntrinsic(i) ||
IsFineDerivativeIntrinsic(i);
}
bool IsFloatClassificationIntrinsic(IntrinsicType i) {
return i == IntrinsicType::kIsFinite || i == IntrinsicType::kIsInf ||
i == IntrinsicType::kIsNan || i == IntrinsicType::kIsNormal;
}
bool IsTextureIntrinsic(IntrinsicType i) {
return IsImageQueryIntrinsic(i) || i == IntrinsicType::kTextureLoad ||
i == IntrinsicType::kTextureGather ||
i == IntrinsicType::kTextureGatherCompare ||
i == IntrinsicType::kTextureSample ||
i == IntrinsicType::kTextureSampleLevel ||
i == IntrinsicType::kTextureSampleBias ||
i == IntrinsicType::kTextureSampleCompare ||
i == IntrinsicType::kTextureSampleCompareLevel ||
i == IntrinsicType::kTextureSampleGrad ||
i == IntrinsicType::kTextureStore;
}
bool IsImageQueryIntrinsic(IntrinsicType i) {
return i == IntrinsicType::kTextureDimensions ||
i == IntrinsicType::kTextureNumLayers ||
i == IntrinsicType::kTextureNumLevels ||
i == IntrinsicType::kTextureNumSamples;
}
bool IsDataPackingIntrinsic(IntrinsicType i) {
return i == IntrinsicType::kPack4x8snorm ||
i == IntrinsicType::kPack4x8unorm ||
i == IntrinsicType::kPack2x16snorm ||
i == IntrinsicType::kPack2x16unorm ||
i == IntrinsicType::kPack2x16float;
}
bool IsDataUnpackingIntrinsic(IntrinsicType i) {
return i == IntrinsicType::kUnpack4x8snorm ||
i == IntrinsicType::kUnpack4x8unorm ||
i == IntrinsicType::kUnpack2x16snorm ||
i == IntrinsicType::kUnpack2x16unorm ||
i == IntrinsicType::kUnpack2x16float;
}
bool IsBarrierIntrinsic(IntrinsicType i) {
return i == IntrinsicType::kWorkgroupBarrier ||
i == IntrinsicType::kStorageBarrier;
}
bool IsAtomicIntrinsic(IntrinsicType i) {
return i == sem::IntrinsicType::kAtomicLoad ||
i == sem::IntrinsicType::kAtomicStore ||
i == sem::IntrinsicType::kAtomicAdd ||
i == sem::IntrinsicType::kAtomicSub ||
i == sem::IntrinsicType::kAtomicMax ||
i == sem::IntrinsicType::kAtomicMin ||
i == sem::IntrinsicType::kAtomicAnd ||
i == sem::IntrinsicType::kAtomicOr ||
i == sem::IntrinsicType::kAtomicXor ||
i == sem::IntrinsicType::kAtomicExchange ||
i == sem::IntrinsicType::kAtomicCompareExchangeWeak;
}
Intrinsic::Intrinsic(IntrinsicType type,
const sem::Type* return_type,
std::vector<Parameter*> parameters,
PipelineStageSet supported_stages,
bool is_deprecated)
: Base(return_type, utils::ToConstPtrVec(parameters)),
type_(type),
supported_stages_(supported_stages),
is_deprecated_(is_deprecated) {
for (auto* parameter : parameters) {
parameter->SetOwner(this);
}
}
Intrinsic::~Intrinsic() = default;
bool Intrinsic::IsCoarseDerivative() const {
return IsCoarseDerivativeIntrinsic(type_);
}
bool Intrinsic::IsFineDerivative() const {
return IsFineDerivativeIntrinsic(type_);
}
bool Intrinsic::IsDerivative() const {
return IsDerivativeIntrinsic(type_);
}
bool Intrinsic::IsFloatClassification() const {
return IsFloatClassificationIntrinsic(type_);
}
bool Intrinsic::IsTexture() const {
return IsTextureIntrinsic(type_);
}
bool Intrinsic::IsImageQuery() const {
return IsImageQueryIntrinsic(type_);
}
bool Intrinsic::IsDataPacking() const {
return IsDataPackingIntrinsic(type_);
}
bool Intrinsic::IsDataUnpacking() const {
return IsDataUnpackingIntrinsic(type_);
}
bool Intrinsic::IsBarrier() const {
return IsBarrierIntrinsic(type_);
}
bool Intrinsic::IsAtomic() const {
return IsAtomicIntrinsic(type_);
}
} // namespace sem
} // namespace tint

View File

@ -1,173 +0,0 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_SEM_INTRINSIC_H_
#define SRC_SEM_INTRINSIC_H_
#include <string>
#include <vector>
#include "src/sem/call_target.h"
#include "src/sem/intrinsic_type.h"
#include "src/sem/pipeline_stage_set.h"
#include "src/utils/hash.h"
namespace tint {
namespace sem {
/// Determines if the given `i` is a coarse derivative
/// @param i the intrinsic type
/// @returns true if the given derivative is coarse.
bool IsCoarseDerivativeIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a fine derivative
/// @param i the intrinsic type
/// @returns true if the given derivative is fine.
bool IsFineDerivativeIntrinsic(IntrinsicType i);
/// Determine if the given `i` is a derivative intrinsic
/// @param i the intrinsic type
/// @returns true if the given `i` is a derivative intrinsic
bool IsDerivativeIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a float classification intrinsic
/// @param i the intrinsic type
/// @returns true if the given `i` is a float intrinsic
bool IsFloatClassificationIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a texture operation intrinsic
/// @param i the intrinsic type
/// @returns true if the given `i` is a texture operation intrinsic
bool IsTextureIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a image query intrinsic
/// @param i the intrinsic type
/// @returns true if the given `i` is a image query intrinsic
bool IsImageQueryIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a data packing intrinsic
/// @param i the intrinsic
/// @returns true if the given `i` is a data packing intrinsic
bool IsDataPackingIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a data unpacking intrinsic
/// @param i the intrinsic
/// @returns true if the given `i` is a data unpacking intrinsic
bool IsDataUnpackingIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a barrier intrinsic
/// @param i the intrinsic
/// @returns true if the given `i` is a barrier intrinsic
bool IsBarrierIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a atomic intrinsic
/// @param i the intrinsic
/// @returns true if the given `i` is a atomic intrinsic
bool IsAtomicIntrinsic(IntrinsicType i);
/// Intrinsic holds the semantic information for an intrinsic function.
class Intrinsic : public Castable<Intrinsic, CallTarget> {
public:
/// Constructor
/// @param type the intrinsic type
/// @param return_type the return type for the intrinsic call
/// @param parameters the parameters for the intrinsic overload
/// @param supported_stages the pipeline stages that this intrinsic can be
/// used in
/// @param is_deprecated true if the particular overload is considered
/// deprecated
Intrinsic(IntrinsicType type,
const sem::Type* return_type,
std::vector<Parameter*> parameters,
PipelineStageSet supported_stages,
bool is_deprecated);
/// Destructor
~Intrinsic() override;
/// @return the type of the intrinsic
IntrinsicType Type() const { return type_; }
/// @return the pipeline stages that this intrinsic can be used in
PipelineStageSet SupportedStages() const { return supported_stages_; }
/// @return true if the intrinsic overload is considered deprecated
bool IsDeprecated() const { return is_deprecated_; }
/// @returns the name of the intrinsic function type. The spelling, including
/// case, matches the name in the WGSL spec.
const char* str() const;
/// @returns true if intrinsic is a coarse derivative intrinsic
bool IsCoarseDerivative() const;
/// @returns true if intrinsic is a fine a derivative intrinsic
bool IsFineDerivative() const;
/// @returns true if intrinsic is a derivative intrinsic
bool IsDerivative() const;
/// @returns true if intrinsic is a float intrinsic
bool IsFloatClassification() const;
/// @returns true if intrinsic is a texture operation intrinsic
bool IsTexture() const;
/// @returns true if intrinsic is a image query intrinsic
bool IsImageQuery() const;
/// @returns true if intrinsic is a data packing intrinsic
bool IsDataPacking() const;
/// @returns true if intrinsic is a data unpacking intrinsic
bool IsDataUnpacking() const;
/// @returns true if intrinsic is a barrier intrinsic
bool IsBarrier() const;
/// @returns true if intrinsic is a atomic intrinsic
bool IsAtomic() const;
private:
const IntrinsicType type_;
const PipelineStageSet supported_stages_;
const bool is_deprecated_;
};
/// Constant value used by the degrees() intrinsic
static constexpr double kRadToDeg = 57.295779513082322865;
/// Constant value used by the radians() intrinsic
static constexpr double kDegToRad = 0.017453292519943295474;
} // namespace sem
} // namespace tint
namespace std {
/// Custom std::hash specialization for tint::sem::Intrinsic
template <>
class hash<tint::sem::Intrinsic> {
public:
/// @param i the Intrinsic to create a hash for
/// @return the hash value
inline std::size_t operator()(const tint::sem::Intrinsic& i) const {
return tint::utils::Hash(i.Type(), i.SupportedStages(), i.ReturnType(),
i.Parameters(), i.IsDeprecated());
}
};
} // namespace std
#endif // SRC_SEM_INTRINSIC_H_

View File

@ -1,132 +0,0 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/sem/intrinsic.h"
#include "gtest/gtest.h"
namespace tint {
namespace sem {
namespace {
struct IntrinsicData {
const char* name;
IntrinsicType intrinsic;
};
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
out << data.name;
return out;
}
using IntrinsicTypeTest = testing::TestWithParam<IntrinsicData>;
TEST_P(IntrinsicTypeTest, Parse) {
auto param = GetParam();
EXPECT_EQ(ParseIntrinsicType(param.name), param.intrinsic);
}
INSTANTIATE_TEST_SUITE_P(
IntrinsicTypeTest,
IntrinsicTypeTest,
testing::Values(
IntrinsicData{"abs", IntrinsicType::kAbs},
IntrinsicData{"acos", IntrinsicType::kAcos},
IntrinsicData{"all", IntrinsicType::kAll},
IntrinsicData{"any", IntrinsicType::kAny},
IntrinsicData{"arrayLength", IntrinsicType::kArrayLength},
IntrinsicData{"asin", IntrinsicType::kAsin},
IntrinsicData{"atan", IntrinsicType::kAtan},
IntrinsicData{"atan2", IntrinsicType::kAtan2},
IntrinsicData{"ceil", IntrinsicType::kCeil},
IntrinsicData{"clamp", IntrinsicType::kClamp},
IntrinsicData{"cos", IntrinsicType::kCos},
IntrinsicData{"cosh", IntrinsicType::kCosh},
IntrinsicData{"countOneBits", IntrinsicType::kCountOneBits},
IntrinsicData{"cross", IntrinsicType::kCross},
IntrinsicData{"determinant", IntrinsicType::kDeterminant},
IntrinsicData{"distance", IntrinsicType::kDistance},
IntrinsicData{"dot", IntrinsicType::kDot},
IntrinsicData{"dpdx", IntrinsicType::kDpdx},
IntrinsicData{"dpdxCoarse", IntrinsicType::kDpdxCoarse},
IntrinsicData{"dpdxFine", IntrinsicType::kDpdxFine},
IntrinsicData{"dpdy", IntrinsicType::kDpdy},
IntrinsicData{"dpdyCoarse", IntrinsicType::kDpdyCoarse},
IntrinsicData{"dpdyFine", IntrinsicType::kDpdyFine},
IntrinsicData{"exp", IntrinsicType::kExp},
IntrinsicData{"exp2", IntrinsicType::kExp2},
IntrinsicData{"faceForward", IntrinsicType::kFaceForward},
IntrinsicData{"floor", IntrinsicType::kFloor},
IntrinsicData{"fma", IntrinsicType::kFma},
IntrinsicData{"fract", IntrinsicType::kFract},
IntrinsicData{"frexp", IntrinsicType::kFrexp},
IntrinsicData{"fwidth", IntrinsicType::kFwidth},
IntrinsicData{"fwidthCoarse", IntrinsicType::kFwidthCoarse},
IntrinsicData{"fwidthFine", IntrinsicType::kFwidthFine},
IntrinsicData{"inverseSqrt", IntrinsicType::kInverseSqrt},
IntrinsicData{"isFinite", IntrinsicType::kIsFinite},
IntrinsicData{"isInf", IntrinsicType::kIsInf},
IntrinsicData{"isNan", IntrinsicType::kIsNan},
IntrinsicData{"isNormal", IntrinsicType::kIsNormal},
IntrinsicData{"ldexp", IntrinsicType::kLdexp},
IntrinsicData{"length", IntrinsicType::kLength},
IntrinsicData{"log", IntrinsicType::kLog},
IntrinsicData{"log2", IntrinsicType::kLog2},
IntrinsicData{"max", IntrinsicType::kMax},
IntrinsicData{"min", IntrinsicType::kMin},
IntrinsicData{"mix", IntrinsicType::kMix},
IntrinsicData{"modf", IntrinsicType::kModf},
IntrinsicData{"normalize", IntrinsicType::kNormalize},
IntrinsicData{"pow", IntrinsicType::kPow},
IntrinsicData{"reflect", IntrinsicType::kReflect},
IntrinsicData{"reverseBits", IntrinsicType::kReverseBits},
IntrinsicData{"round", IntrinsicType::kRound},
IntrinsicData{"select", IntrinsicType::kSelect},
IntrinsicData{"sign", IntrinsicType::kSign},
IntrinsicData{"sin", IntrinsicType::kSin},
IntrinsicData{"sinh", IntrinsicType::kSinh},
IntrinsicData{"smoothStep", IntrinsicType::kSmoothStep},
IntrinsicData{"sqrt", IntrinsicType::kSqrt},
IntrinsicData{"step", IntrinsicType::kStep},
IntrinsicData{"storageBarrier", IntrinsicType::kStorageBarrier},
IntrinsicData{"tan", IntrinsicType::kTan},
IntrinsicData{"tanh", IntrinsicType::kTanh},
IntrinsicData{"textureDimensions", IntrinsicType::kTextureDimensions},
IntrinsicData{"textureLoad", IntrinsicType::kTextureLoad},
IntrinsicData{"textureNumLayers", IntrinsicType::kTextureNumLayers},
IntrinsicData{"textureNumLevels", IntrinsicType::kTextureNumLevels},
IntrinsicData{"textureNumSamples", IntrinsicType::kTextureNumSamples},
IntrinsicData{"textureSample", IntrinsicType::kTextureSample},
IntrinsicData{"textureSampleBias", IntrinsicType::kTextureSampleBias},
IntrinsicData{"textureSampleCompare",
IntrinsicType::kTextureSampleCompare},
IntrinsicData{"textureSampleCompareLevel",
IntrinsicType::kTextureSampleCompareLevel},
IntrinsicData{"textureSampleGrad", IntrinsicType::kTextureSampleGrad},
IntrinsicData{"textureSampleLevel", IntrinsicType::kTextureSampleLevel},
IntrinsicData{"trunc", IntrinsicType::kTrunc},
IntrinsicData{"unpack2x16float", IntrinsicType::kUnpack2x16float},
IntrinsicData{"unpack2x16snorm", IntrinsicType::kUnpack2x16snorm},
IntrinsicData{"unpack2x16unorm", IntrinsicType::kUnpack2x16unorm},
IntrinsicData{"unpack4x8snorm", IntrinsicType::kUnpack4x8snorm},
IntrinsicData{"unpack4x8unorm", IntrinsicType::kUnpack4x8unorm},
IntrinsicData{"workgroupBarrier", IntrinsicType::kWorkgroupBarrier}));
TEST_F(IntrinsicTypeTest, ParseNoMatch) {
EXPECT_EQ(ParseIntrinsicType("not_intrinsic"), IntrinsicType::kNone);
}
} // namespace
} // namespace sem
} // namespace tint

View File

@ -1,560 +0,0 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen
// using the template:
// src/sem/intrinsic_type.cc.tmpl
// and the intrinsic defintion file:
// src/intrinsics.def
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#include "src/sem/intrinsic_type.h"
#include <sstream>
namespace tint {
namespace sem {
IntrinsicType ParseIntrinsicType(const std::string& name) {
if (name == "abs") {
return IntrinsicType::kAbs;
}
if (name == "acos") {
return IntrinsicType::kAcos;
}
if (name == "all") {
return IntrinsicType::kAll;
}
if (name == "any") {
return IntrinsicType::kAny;
}
if (name == "arrayLength") {
return IntrinsicType::kArrayLength;
}
if (name == "asin") {
return IntrinsicType::kAsin;
}
if (name == "atan") {
return IntrinsicType::kAtan;
}
if (name == "atan2") {
return IntrinsicType::kAtan2;
}
if (name == "ceil") {
return IntrinsicType::kCeil;
}
if (name == "clamp") {
return IntrinsicType::kClamp;
}
if (name == "cos") {
return IntrinsicType::kCos;
}
if (name == "cosh") {
return IntrinsicType::kCosh;
}
if (name == "countOneBits") {
return IntrinsicType::kCountOneBits;
}
if (name == "cross") {
return IntrinsicType::kCross;
}
if (name == "degrees") {
return IntrinsicType::kDegrees;
}
if (name == "determinant") {
return IntrinsicType::kDeterminant;
}
if (name == "distance") {
return IntrinsicType::kDistance;
}
if (name == "dot") {
return IntrinsicType::kDot;
}
if (name == "dpdx") {
return IntrinsicType::kDpdx;
}
if (name == "dpdxCoarse") {
return IntrinsicType::kDpdxCoarse;
}
if (name == "dpdxFine") {
return IntrinsicType::kDpdxFine;
}
if (name == "dpdy") {
return IntrinsicType::kDpdy;
}
if (name == "dpdyCoarse") {
return IntrinsicType::kDpdyCoarse;
}
if (name == "dpdyFine") {
return IntrinsicType::kDpdyFine;
}
if (name == "exp") {
return IntrinsicType::kExp;
}
if (name == "exp2") {
return IntrinsicType::kExp2;
}
if (name == "faceForward") {
return IntrinsicType::kFaceForward;
}
if (name == "floor") {
return IntrinsicType::kFloor;
}
if (name == "fma") {
return IntrinsicType::kFma;
}
if (name == "fract") {
return IntrinsicType::kFract;
}
if (name == "frexp") {
return IntrinsicType::kFrexp;
}
if (name == "fwidth") {
return IntrinsicType::kFwidth;
}
if (name == "fwidthCoarse") {
return IntrinsicType::kFwidthCoarse;
}
if (name == "fwidthFine") {
return IntrinsicType::kFwidthFine;
}
if (name == "inverseSqrt") {
return IntrinsicType::kInverseSqrt;
}
if (name == "isFinite") {
return IntrinsicType::kIsFinite;
}
if (name == "isInf") {
return IntrinsicType::kIsInf;
}
if (name == "isNan") {
return IntrinsicType::kIsNan;
}
if (name == "isNormal") {
return IntrinsicType::kIsNormal;
}
if (name == "ldexp") {
return IntrinsicType::kLdexp;
}
if (name == "length") {
return IntrinsicType::kLength;
}
if (name == "log") {
return IntrinsicType::kLog;
}
if (name == "log2") {
return IntrinsicType::kLog2;
}
if (name == "max") {
return IntrinsicType::kMax;
}
if (name == "min") {
return IntrinsicType::kMin;
}
if (name == "mix") {
return IntrinsicType::kMix;
}
if (name == "modf") {
return IntrinsicType::kModf;
}
if (name == "normalize") {
return IntrinsicType::kNormalize;
}
if (name == "pack2x16float") {
return IntrinsicType::kPack2x16float;
}
if (name == "pack2x16snorm") {
return IntrinsicType::kPack2x16snorm;
}
if (name == "pack2x16unorm") {
return IntrinsicType::kPack2x16unorm;
}
if (name == "pack4x8snorm") {
return IntrinsicType::kPack4x8snorm;
}
if (name == "pack4x8unorm") {
return IntrinsicType::kPack4x8unorm;
}
if (name == "pow") {
return IntrinsicType::kPow;
}
if (name == "radians") {
return IntrinsicType::kRadians;
}
if (name == "reflect") {
return IntrinsicType::kReflect;
}
if (name == "refract") {
return IntrinsicType::kRefract;
}
if (name == "reverseBits") {
return IntrinsicType::kReverseBits;
}
if (name == "round") {
return IntrinsicType::kRound;
}
if (name == "select") {
return IntrinsicType::kSelect;
}
if (name == "sign") {
return IntrinsicType::kSign;
}
if (name == "sin") {
return IntrinsicType::kSin;
}
if (name == "sinh") {
return IntrinsicType::kSinh;
}
if (name == "smoothStep") {
return IntrinsicType::kSmoothStep;
}
if (name == "sqrt") {
return IntrinsicType::kSqrt;
}
if (name == "step") {
return IntrinsicType::kStep;
}
if (name == "storageBarrier") {
return IntrinsicType::kStorageBarrier;
}
if (name == "tan") {
return IntrinsicType::kTan;
}
if (name == "tanh") {
return IntrinsicType::kTanh;
}
if (name == "transpose") {
return IntrinsicType::kTranspose;
}
if (name == "trunc") {
return IntrinsicType::kTrunc;
}
if (name == "unpack2x16float") {
return IntrinsicType::kUnpack2x16float;
}
if (name == "unpack2x16snorm") {
return IntrinsicType::kUnpack2x16snorm;
}
if (name == "unpack2x16unorm") {
return IntrinsicType::kUnpack2x16unorm;
}
if (name == "unpack4x8snorm") {
return IntrinsicType::kUnpack4x8snorm;
}
if (name == "unpack4x8unorm") {
return IntrinsicType::kUnpack4x8unorm;
}
if (name == "workgroupBarrier") {
return IntrinsicType::kWorkgroupBarrier;
}
if (name == "textureDimensions") {
return IntrinsicType::kTextureDimensions;
}
if (name == "textureGather") {
return IntrinsicType::kTextureGather;
}
if (name == "textureGatherCompare") {
return IntrinsicType::kTextureGatherCompare;
}
if (name == "textureNumLayers") {
return IntrinsicType::kTextureNumLayers;
}
if (name == "textureNumLevels") {
return IntrinsicType::kTextureNumLevels;
}
if (name == "textureNumSamples") {
return IntrinsicType::kTextureNumSamples;
}
if (name == "textureSample") {
return IntrinsicType::kTextureSample;
}
if (name == "textureSampleBias") {
return IntrinsicType::kTextureSampleBias;
}
if (name == "textureSampleCompare") {
return IntrinsicType::kTextureSampleCompare;
}
if (name == "textureSampleCompareLevel") {
return IntrinsicType::kTextureSampleCompareLevel;
}
if (name == "textureSampleGrad") {
return IntrinsicType::kTextureSampleGrad;
}
if (name == "textureSampleLevel") {
return IntrinsicType::kTextureSampleLevel;
}
if (name == "textureStore") {
return IntrinsicType::kTextureStore;
}
if (name == "textureLoad") {
return IntrinsicType::kTextureLoad;
}
if (name == "atomicLoad") {
return IntrinsicType::kAtomicLoad;
}
if (name == "atomicStore") {
return IntrinsicType::kAtomicStore;
}
if (name == "atomicAdd") {
return IntrinsicType::kAtomicAdd;
}
if (name == "atomicSub") {
return IntrinsicType::kAtomicSub;
}
if (name == "atomicMax") {
return IntrinsicType::kAtomicMax;
}
if (name == "atomicMin") {
return IntrinsicType::kAtomicMin;
}
if (name == "atomicAnd") {
return IntrinsicType::kAtomicAnd;
}
if (name == "atomicOr") {
return IntrinsicType::kAtomicOr;
}
if (name == "atomicXor") {
return IntrinsicType::kAtomicXor;
}
if (name == "atomicExchange") {
return IntrinsicType::kAtomicExchange;
}
if (name == "atomicCompareExchangeWeak") {
return IntrinsicType::kAtomicCompareExchangeWeak;
}
return IntrinsicType::kNone;
}
const char* str(IntrinsicType i) {
switch (i) {
case IntrinsicType::kNone:
return "<none>";
case IntrinsicType::kAbs:
return "abs";
case IntrinsicType::kAcos:
return "acos";
case IntrinsicType::kAll:
return "all";
case IntrinsicType::kAny:
return "any";
case IntrinsicType::kArrayLength:
return "arrayLength";
case IntrinsicType::kAsin:
return "asin";
case IntrinsicType::kAtan:
return "atan";
case IntrinsicType::kAtan2:
return "atan2";
case IntrinsicType::kCeil:
return "ceil";
case IntrinsicType::kClamp:
return "clamp";
case IntrinsicType::kCos:
return "cos";
case IntrinsicType::kCosh:
return "cosh";
case IntrinsicType::kCountOneBits:
return "countOneBits";
case IntrinsicType::kCross:
return "cross";
case IntrinsicType::kDegrees:
return "degrees";
case IntrinsicType::kDeterminant:
return "determinant";
case IntrinsicType::kDistance:
return "distance";
case IntrinsicType::kDot:
return "dot";
case IntrinsicType::kDpdx:
return "dpdx";
case IntrinsicType::kDpdxCoarse:
return "dpdxCoarse";
case IntrinsicType::kDpdxFine:
return "dpdxFine";
case IntrinsicType::kDpdy:
return "dpdy";
case IntrinsicType::kDpdyCoarse:
return "dpdyCoarse";
case IntrinsicType::kDpdyFine:
return "dpdyFine";
case IntrinsicType::kExp:
return "exp";
case IntrinsicType::kExp2:
return "exp2";
case IntrinsicType::kFaceForward:
return "faceForward";
case IntrinsicType::kFloor:
return "floor";
case IntrinsicType::kFma:
return "fma";
case IntrinsicType::kFract:
return "fract";
case IntrinsicType::kFrexp:
return "frexp";
case IntrinsicType::kFwidth:
return "fwidth";
case IntrinsicType::kFwidthCoarse:
return "fwidthCoarse";
case IntrinsicType::kFwidthFine:
return "fwidthFine";
case IntrinsicType::kInverseSqrt:
return "inverseSqrt";
case IntrinsicType::kIsFinite:
return "isFinite";
case IntrinsicType::kIsInf:
return "isInf";
case IntrinsicType::kIsNan:
return "isNan";
case IntrinsicType::kIsNormal:
return "isNormal";
case IntrinsicType::kLdexp:
return "ldexp";
case IntrinsicType::kLength:
return "length";
case IntrinsicType::kLog:
return "log";
case IntrinsicType::kLog2:
return "log2";
case IntrinsicType::kMax:
return "max";
case IntrinsicType::kMin:
return "min";
case IntrinsicType::kMix:
return "mix";
case IntrinsicType::kModf:
return "modf";
case IntrinsicType::kNormalize:
return "normalize";
case IntrinsicType::kPack2x16float:
return "pack2x16float";
case IntrinsicType::kPack2x16snorm:
return "pack2x16snorm";
case IntrinsicType::kPack2x16unorm:
return "pack2x16unorm";
case IntrinsicType::kPack4x8snorm:
return "pack4x8snorm";
case IntrinsicType::kPack4x8unorm:
return "pack4x8unorm";
case IntrinsicType::kPow:
return "pow";
case IntrinsicType::kRadians:
return "radians";
case IntrinsicType::kReflect:
return "reflect";
case IntrinsicType::kRefract:
return "refract";
case IntrinsicType::kReverseBits:
return "reverseBits";
case IntrinsicType::kRound:
return "round";
case IntrinsicType::kSelect:
return "select";
case IntrinsicType::kSign:
return "sign";
case IntrinsicType::kSin:
return "sin";
case IntrinsicType::kSinh:
return "sinh";
case IntrinsicType::kSmoothStep:
return "smoothStep";
case IntrinsicType::kSqrt:
return "sqrt";
case IntrinsicType::kStep:
return "step";
case IntrinsicType::kStorageBarrier:
return "storageBarrier";
case IntrinsicType::kTan:
return "tan";
case IntrinsicType::kTanh:
return "tanh";
case IntrinsicType::kTranspose:
return "transpose";
case IntrinsicType::kTrunc:
return "trunc";
case IntrinsicType::kUnpack2x16float:
return "unpack2x16float";
case IntrinsicType::kUnpack2x16snorm:
return "unpack2x16snorm";
case IntrinsicType::kUnpack2x16unorm:
return "unpack2x16unorm";
case IntrinsicType::kUnpack4x8snorm:
return "unpack4x8snorm";
case IntrinsicType::kUnpack4x8unorm:
return "unpack4x8unorm";
case IntrinsicType::kWorkgroupBarrier:
return "workgroupBarrier";
case IntrinsicType::kTextureDimensions:
return "textureDimensions";
case IntrinsicType::kTextureGather:
return "textureGather";
case IntrinsicType::kTextureGatherCompare:
return "textureGatherCompare";
case IntrinsicType::kTextureNumLayers:
return "textureNumLayers";
case IntrinsicType::kTextureNumLevels:
return "textureNumLevels";
case IntrinsicType::kTextureNumSamples:
return "textureNumSamples";
case IntrinsicType::kTextureSample:
return "textureSample";
case IntrinsicType::kTextureSampleBias:
return "textureSampleBias";
case IntrinsicType::kTextureSampleCompare:
return "textureSampleCompare";
case IntrinsicType::kTextureSampleCompareLevel:
return "textureSampleCompareLevel";
case IntrinsicType::kTextureSampleGrad:
return "textureSampleGrad";
case IntrinsicType::kTextureSampleLevel:
return "textureSampleLevel";
case IntrinsicType::kTextureStore:
return "textureStore";
case IntrinsicType::kTextureLoad:
return "textureLoad";
case IntrinsicType::kAtomicLoad:
return "atomicLoad";
case IntrinsicType::kAtomicStore:
return "atomicStore";
case IntrinsicType::kAtomicAdd:
return "atomicAdd";
case IntrinsicType::kAtomicSub:
return "atomicSub";
case IntrinsicType::kAtomicMax:
return "atomicMax";
case IntrinsicType::kAtomicMin:
return "atomicMin";
case IntrinsicType::kAtomicAnd:
return "atomicAnd";
case IntrinsicType::kAtomicOr:
return "atomicOr";
case IntrinsicType::kAtomicXor:
return "atomicXor";
case IntrinsicType::kAtomicExchange:
return "atomicExchange";
case IntrinsicType::kAtomicCompareExchangeWeak:
return "atomicCompareExchangeWeak";
}
return "<unknown>";
}
std::ostream& operator<<(std::ostream& out, IntrinsicType i) {
out << str(i);
return out;
}
} // namespace sem
} // namespace tint

View File

@ -1,45 +0,0 @@
{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/intrinsic-gen to generate intrinsic_type.h
See:
* tools/cmd/intrinsic-gen/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}
#ifndef SRC_SEM_INTRINSIC_TYPE_H_
#define SRC_SEM_INTRINSIC_TYPE_H_
#include <sstream>
#include <string>
namespace tint {
namespace sem {
/// Enumerator of all intrinsic functions
enum class IntrinsicType {
kNone = -1,
{{- range .Sem.Functions }}
k{{Title .Name}},
{{- end }}
};
/// Matches the IntrinsicType by name
/// @param name the intrinsic name to parse
/// @returns the parsed IntrinsicType, or IntrinsicType::kNone if `name` did not
/// match any intrinsic.
IntrinsicType ParseIntrinsicType(const std::string& name);
/// @returns the name of the intrinsic function type. The spelling, including
/// case, matches the name in the WGSL spec.
const char* str(IntrinsicType i);
/// Emits the name of the intrinsic function type. The spelling, including case,
/// matches the name in the WGSL spec.
std::ostream& operator<<(std::ostream& out, IntrinsicType i);
} // namespace sem
} // namespace tint
#endif // SRC_SEM_INTRINSIC_TYPE_H_

View File

@ -13,11 +13,11 @@
// limitations under the License. // limitations under the License.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen // File generated by tools/builtin-gen
// using the template: // using the template:
// src/sem/parameter_usage.cc.tmpl // src/sem/parameter_usage.cc.tmpl
// and the intrinsic defintion file: // and the builtin defintion file:
// src/intrinsics.def // src/builtins.def
// //
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -1,9 +1,9 @@
{{- /* {{- /*
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Template file for use with tools/intrinsic-gen to generate parameter_usage.cc Template file for use with tools/builtin-gen to generate parameter_usage.cc
See: See:
* tools/cmd/intrinsic-gen/gen for structures used by this template * tools/cmd/builtin-gen/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax * https://golang.org/pkg/text/template/ for documentation on the template syntax
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
*/ -}} */ -}}

View File

@ -13,11 +13,11 @@
// limitations under the License. // limitations under the License.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen // File generated by tools/builtin-gen
// using the template: // using the template:
// src/sem/parameter_usage.h.tmpl // src/sem/parameter_usage.h.tmpl
// and the intrinsic defintion file: // and the builtin defintion file:
// src/intrinsics.def // src/builtins.def
// //
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -1,9 +1,9 @@
{{- /* {{- /*
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Template file for use with tools/intrinsic-gen to generate parameter_usage.h Template file for use with tools/builtin-gen to generate parameter_usage.h
See: See:
* tools/cmd/intrinsic-gen/gen for structures used by this template * tools/cmd/builtin-gen/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax * https://golang.org/pkg/text/template/ for documentation on the template syntax
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
*/ -}} */ -}}

View File

@ -34,7 +34,7 @@ namespace transform {
ArrayLengthFromUniform::ArrayLengthFromUniform() = default; ArrayLengthFromUniform::ArrayLengthFromUniform() = default;
ArrayLengthFromUniform::~ArrayLengthFromUniform() = default; ArrayLengthFromUniform::~ArrayLengthFromUniform() = default;
/// Iterate over all arrayLength() intrinsics that operate on /// Iterate over all arrayLength() builtins that operate on
/// storage buffer variables. /// storage buffer variables.
/// @param ctx the CloneContext. /// @param ctx the CloneContext.
/// @param functor of type void(const ast::CallExpression*, const /// @param functor of type void(const ast::CallExpression*, const
@ -46,7 +46,7 @@ template <typename F>
static void IterateArrayLengthOnStorageVar(CloneContext& ctx, F&& functor) { static void IterateArrayLengthOnStorageVar(CloneContext& ctx, F&& functor) {
auto& sem = ctx.src->Sem(); auto& sem = ctx.src->Sem();
// Find all calls to the arrayLength() intrinsic. // Find all calls to the arrayLength() builtin.
for (auto* node : ctx.src->ASTNodes().Objects()) { for (auto* node : ctx.src->ASTNodes().Objects()) {
auto* call_expr = node->As<ast::CallExpression>(); auto* call_expr = node->As<ast::CallExpression>();
if (!call_expr) { if (!call_expr) {
@ -54,8 +54,8 @@ static void IterateArrayLengthOnStorageVar(CloneContext& ctx, F&& functor) {
} }
auto* call = sem.Get(call_expr); auto* call = sem.Get(call_expr);
auto* intrinsic = call->Target()->As<sem::Intrinsic>(); auto* builtin = call->Target()->As<sem::Builtin>();
if (!intrinsic || intrinsic->Type() != sem::IntrinsicType::kArrayLength) { if (!builtin || builtin->Type() != sem::BuiltinType::kArrayLength) {
continue; continue;
} }
@ -98,8 +98,8 @@ bool ArrayLengthFromUniform::ShouldRun(const Program* program,
const DataMap&) const { const DataMap&) const {
for (auto* fn : program->AST().Functions()) { for (auto* fn : program->AST().Functions()) {
if (auto* sem_fn = program->Sem().Get(fn)) { if (auto* sem_fn = program->Sem().Get(fn)) {
for (auto* intrinsic : sem_fn->DirectlyCalledIntrinsics()) { for (auto* builtin : sem_fn->DirectlyCalledBuiltins()) {
if (intrinsic->Type() == sem::IntrinsicType::kArrayLength) { if (builtin->Type() == sem::BuiltinType::kArrayLength) {
return true; return true;
} }
} }

View File

@ -84,7 +84,7 @@ class ArrayLengthFromUniform
}; };
/// Information produced about what the transform did. /// Information produced about what the transform did.
/// If there were no calls to the arrayLength() intrinsic, then no Result will /// If there were no calls to the arrayLength() builtin, then no Result will
/// be emitted. /// be emitted.
struct Result : public Castable<Result, transform::Data> { struct Result : public Castable<Result, transform::Data> {
/// Constructor /// Constructor

View File

@ -76,8 +76,8 @@ bool CalculateArrayLength::ShouldRun(const Program* program,
const DataMap&) const { const DataMap&) const {
for (auto* fn : program->AST().Functions()) { for (auto* fn : program->AST().Functions()) {
if (auto* sem_fn = program->Sem().Get(fn)) { if (auto* sem_fn = program->Sem().Get(fn)) {
for (auto* intrinsic : sem_fn->DirectlyCalledIntrinsics()) { for (auto* builtin : sem_fn->DirectlyCalledBuiltins()) {
if (intrinsic->Type() == sem::IntrinsicType::kArrayLength) { if (builtin->Type() == sem::BuiltinType::kArrayLength) {
return true; return true;
} }
} }
@ -143,8 +143,8 @@ void CalculateArrayLength::Run(CloneContext& ctx,
for (auto* node : ctx.src->ASTNodes().Objects()) { for (auto* node : ctx.src->ASTNodes().Objects()) {
if (auto* call_expr = node->As<ast::CallExpression>()) { if (auto* call_expr = node->As<ast::CallExpression>()) {
auto* call = sem.Get(call_expr); auto* call = sem.Get(call_expr);
if (auto* intrinsic = call->Target()->As<sem::Intrinsic>()) { if (auto* builtin = call->Target()->As<sem::Builtin>()) {
if (intrinsic->Type() == sem::IntrinsicType::kArrayLength) { if (builtin->Type() == sem::BuiltinType::kArrayLength) {
// We're dealing with an arrayLength() call // We're dealing with an arrayLength() call
// A runtime-sized array can only appear as the store type of a // A runtime-sized array can only appear as the store type of a

View File

@ -71,7 +71,7 @@ struct CombineSamplers::State {
/// Placeholder global samplers used when a function contains texture-only /// Placeholder global samplers used when a function contains texture-only
/// references (one comparison sampler, one regular). These are also used as /// references (one comparison sampler, one regular). These are also used as
/// temporary sampler parameters to the texture intrinsics to satsify the WGSL /// temporary sampler parameters to the texture builtins to satisfy the WGSL
/// resolver, but are then ignored and removed by the GLSL writer. /// resolver, but are then ignored and removed by the GLSL writer.
const ast::Variable* placeholder_samplers_[2] = {}; const ast::Variable* placeholder_samplers_[2] = {};
@ -210,9 +210,9 @@ struct CombineSamplers::State {
-> const ast::Expression* { -> const ast::Expression* {
if (auto* call = sem.Get(expr)) { if (auto* call = sem.Get(expr)) {
ast::ExpressionList args; ast::ExpressionList args;
// Replace all texture intrinsic calls. // Replace all texture builtin calls.
if (auto* intrinsic = call->Target()->As<sem::Intrinsic>()) { if (auto* builtin = call->Target()->As<sem::Builtin>()) {
const auto& signature = intrinsic->Signature(); const auto& signature = builtin->Signature();
int sampler_index = signature.IndexOf(sem::ParameterUsage::kSampler); int sampler_index = signature.IndexOf(sem::ParameterUsage::kSampler);
int texture_index = signature.IndexOf(sem::ParameterUsage::kTexture); int texture_index = signature.IndexOf(sem::ParameterUsage::kTexture);
if (texture_index == -1) { if (texture_index == -1) {

View File

@ -38,9 +38,9 @@ namespace transform {
/// parameter. In this case, a new parameter is added to the function /// parameter. In this case, a new parameter is added to the function
/// signature. All separate texture/sampler parameters are removed. /// signature. All separate texture/sampler parameters are removed.
/// ///
/// All texture intrinsic callsites are modified to pass the combined /// All texture builtin callsites are modified to pass the combined
/// texture/sampler as the first argument, and separate texture/sampler /// texture/sampler as the first argument, and separate texture/sampler
/// arugments are removed. /// arguments are removed.
/// ///
/// Note that the sampler may be null, indicating that only a texture /// Note that the sampler may be null, indicating that only a texture
/// reference was required (e.g., textureLoad). In this case, a /// reference was required (e.g., textureLoad). In this case, a

View File

@ -115,7 +115,7 @@ struct LoadStoreKey {
struct AtomicKey { struct AtomicKey {
sem::Type const* buf_ty = nullptr; // buffer type sem::Type const* buf_ty = nullptr; // buffer type
sem::Type const* el_ty = nullptr; // element type sem::Type const* el_ty = nullptr; // element type
sem::IntrinsicType const op; // atomic op sem::BuiltinType const op; // atomic op
bool operator==(const AtomicKey& rhs) const { bool operator==(const AtomicKey& rhs) const {
return buf_ty == rhs.buf_ty && el_ty == rhs.el_ty && op == rhs.op; return buf_ty == rhs.buf_ty && el_ty == rhs.el_ty && op == rhs.op;
} }
@ -224,41 +224,41 @@ DecomposeMemoryAccess::Intrinsic* IntrinsicStoreFor(
/// @returns a DecomposeMemoryAccess::Intrinsic attribute that can be applied /// @returns a DecomposeMemoryAccess::Intrinsic attribute that can be applied
/// to a stub function for the atomic op and the type `ty`. /// to a stub function for the atomic op and the type `ty`.
DecomposeMemoryAccess::Intrinsic* IntrinsicAtomicFor(ProgramBuilder* builder, DecomposeMemoryAccess::Intrinsic* IntrinsicAtomicFor(ProgramBuilder* builder,
sem::IntrinsicType ity, sem::BuiltinType ity,
const sem::Type* ty) { const sem::Type* ty) {
auto op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicLoad; auto op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicLoad;
switch (ity) { switch (ity) {
case sem::IntrinsicType::kAtomicLoad: case sem::BuiltinType::kAtomicLoad:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicLoad; op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicLoad;
break; break;
case sem::IntrinsicType::kAtomicStore: case sem::BuiltinType::kAtomicStore:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicStore; op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicStore;
break; break;
case sem::IntrinsicType::kAtomicAdd: case sem::BuiltinType::kAtomicAdd:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicAdd; op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicAdd;
break; break;
case sem::IntrinsicType::kAtomicSub: case sem::BuiltinType::kAtomicSub:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicSub; op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicSub;
break; break;
case sem::IntrinsicType::kAtomicMax: case sem::BuiltinType::kAtomicMax:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicMax; op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicMax;
break; break;
case sem::IntrinsicType::kAtomicMin: case sem::BuiltinType::kAtomicMin:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicMin; op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicMin;
break; break;
case sem::IntrinsicType::kAtomicAnd: case sem::BuiltinType::kAtomicAnd:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicAnd; op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicAnd;
break; break;
case sem::IntrinsicType::kAtomicOr: case sem::BuiltinType::kAtomicOr:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicOr; op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicOr;
break; break;
case sem::IntrinsicType::kAtomicXor: case sem::BuiltinType::kAtomicXor:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicXor; op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicXor;
break; break;
case sem::IntrinsicType::kAtomicExchange: case sem::BuiltinType::kAtomicExchange:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicExchange; op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicExchange;
break; break;
case sem::IntrinsicType::kAtomicCompareExchangeWeak: case sem::BuiltinType::kAtomicCompareExchangeWeak:
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicCompareExchangeWeak; op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicCompareExchangeWeak;
break; break;
default: default:
@ -641,7 +641,7 @@ struct DecomposeMemoryAccess::State {
/// @return the name of the function that performs the load /// @return the name of the function that performs the load
Symbol AtomicFunc(const sem::Type* buf_ty, Symbol AtomicFunc(const sem::Type* buf_ty,
const sem::Type* el_ty, const sem::Type* el_ty,
const sem::Intrinsic* intrinsic, const sem::Builtin* intrinsic,
const sem::VariableUser* var_user) { const sem::VariableUser* var_user) {
auto op = intrinsic->Type(); auto op = intrinsic->Type();
return utils::GetOrCreate(atomic_funcs, AtomicKey{buf_ty, el_ty, op}, [&] { return utils::GetOrCreate(atomic_funcs, AtomicKey{buf_ty, el_ty, op}, [&] {
@ -921,15 +921,15 @@ void DecomposeMemoryAccess::Run(CloneContext& ctx,
if (auto* call_expr = node->As<ast::CallExpression>()) { if (auto* call_expr = node->As<ast::CallExpression>()) {
auto* call = sem.Get(call_expr); auto* call = sem.Get(call_expr);
if (auto* intrinsic = call->Target()->As<sem::Intrinsic>()) { if (auto* builtin = call->Target()->As<sem::Builtin>()) {
if (intrinsic->Type() == sem::IntrinsicType::kArrayLength) { if (builtin->Type() == sem::BuiltinType::kArrayLength) {
// arrayLength(X) // arrayLength(X)
// Don't convert X into a load, this intrinsic actually requires the // Don't convert X into a load, this builtin actually requires the
// real pointer. // real pointer.
state.TakeAccess(call_expr->args[0]); state.TakeAccess(call_expr->args[0]);
continue; continue;
} }
if (intrinsic->IsAtomic()) { if (builtin->IsAtomic()) {
if (auto access = state.TakeAccess(call_expr->args[0])) { if (auto access = state.TakeAccess(call_expr->args[0])) {
// atomic___(X) // atomic___(X)
ctx.Replace(call_expr, [=, &ctx, &state] { ctx.Replace(call_expr, [=, &ctx, &state] {
@ -937,9 +937,8 @@ void DecomposeMemoryAccess::Run(CloneContext& ctx,
auto* offset = access.offset->Build(ctx); auto* offset = access.offset->Build(ctx);
auto* buf_ty = access.var->Type()->UnwrapRef(); auto* buf_ty = access.var->Type()->UnwrapRef();
auto* el_ty = access.type->UnwrapRef()->As<sem::Atomic>()->Type(); auto* el_ty = access.type->UnwrapRef()->As<sem::Atomic>()->Type();
Symbol func = Symbol func = state.AtomicFunc(
state.AtomicFunc(buf_ty, el_ty, intrinsic, buf_ty, el_ty, builtin, access.var->As<sem::VariableUser>());
access.var->As<sem::VariableUser>());
ast::ExpressionList args{ctx.Clone(buf), offset}; ast::ExpressionList args{ctx.Clone(buf), offset};
for (size_t i = 1; i < call_expr->args.size(); i++) { for (size_t i = 1; i < call_expr->args.size(); i++) {

View File

@ -46,10 +46,9 @@ void ExternalTextureTransform::Run(CloneContext& ctx,
// Scan the AST nodes for calls to textureLoad or textureSampleLevel. // Scan the AST nodes for calls to textureLoad or textureSampleLevel.
for (auto* node : ctx.src->ASTNodes().Objects()) { for (auto* node : ctx.src->ASTNodes().Objects()) {
if (auto* call_expr = node->As<ast::CallExpression>()) { if (auto* call_expr = node->As<ast::CallExpression>()) {
if (auto* intrinsic = if (auto* builtin = sem.Get(call_expr)->Target()->As<sem::Builtin>()) {
sem.Get(call_expr)->Target()->As<sem::Intrinsic>()) { if (builtin->Type() == sem::BuiltinType::kTextureLoad ||
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad || builtin->Type() == sem::BuiltinType::kTextureSampleLevel) {
intrinsic->Type() == sem::IntrinsicType::kTextureSampleLevel) {
// When a textureLoad or textureSampleLevel has been identified, check // When a textureLoad or textureSampleLevel has been identified, check
// if the first parameter is an external texture. // if the first parameter is an external texture.
if (auto* var = if (auto* var =
@ -58,7 +57,7 @@ void ExternalTextureTransform::Run(CloneContext& ctx,
->Type() ->Type()
->UnwrapRef() ->UnwrapRef()
->Is<sem::ExternalTexture>()) { ->Is<sem::ExternalTexture>()) {
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad && if (builtin->Type() == sem::BuiltinType::kTextureLoad &&
call_expr->args.size() != 2) { call_expr->args.size() != 2) {
TINT_ICE(Transform, ctx.dst->Diagnostics()) TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "expected textureLoad call with a texture_external to " << "expected textureLoad call with a texture_external to "
@ -66,8 +65,7 @@ void ExternalTextureTransform::Run(CloneContext& ctx,
<< call_expr->args.size() << " parameters"; << call_expr->args.size() << " parameters";
} }
if (intrinsic->Type() == if (builtin->Type() == sem::BuiltinType::kTextureSampleLevel &&
sem::IntrinsicType::kTextureSampleLevel &&
call_expr->args.size() != 3) { call_expr->args.size() != 3) {
TINT_ICE(Transform, ctx.dst->Diagnostics()) TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "expected textureSampleLevel call with a " << "expected textureSampleLevel call with a "
@ -82,12 +80,12 @@ void ExternalTextureTransform::Run(CloneContext& ctx,
auto* externalTextureParam = ctx.Clone(call_expr->args[0]); auto* externalTextureParam = ctx.Clone(call_expr->args[0]);
ast::ExpressionList params; ast::ExpressionList params;
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad) { if (builtin->Type() == sem::BuiltinType::kTextureLoad) {
auto* coordsParam = ctx.Clone(call_expr->args[1]); auto* coordsParam = ctx.Clone(call_expr->args[1]);
auto* levelParam = ctx.dst->Expr(0); auto* levelParam = ctx.dst->Expr(0);
params = {externalTextureParam, coordsParam, levelParam}; params = {externalTextureParam, coordsParam, levelParam};
} else if (intrinsic->Type() == } else if (builtin->Type() ==
sem::IntrinsicType::kTextureSampleLevel) { sem::BuiltinType::kTextureSampleLevel) {
auto* samplerParam = ctx.Clone(call_expr->args[1]); auto* samplerParam = ctx.Clone(call_expr->args[1]);
auto* coordsParam = ctx.Clone(call_expr->args[2]); auto* coordsParam = ctx.Clone(call_expr->args[2]);
auto* levelParam = ctx.dst->Expr(0.0f); auto* levelParam = ctx.dst->Expr(0.0f);

View File

@ -148,11 +148,11 @@ struct MultiplanarExternalTexture::State {
// textureLoadExternal and textureSampleExternal calls. // textureLoadExternal and textureSampleExternal calls.
ctx.ReplaceAll( ctx.ReplaceAll(
[&](const ast::CallExpression* expr) -> const ast::CallExpression* { [&](const ast::CallExpression* expr) -> const ast::CallExpression* {
auto* intrinsic = sem.Get(expr)->Target()->As<sem::Intrinsic>(); auto* builtin = sem.Get(expr)->Target()->As<sem::Builtin>();
if (intrinsic && !intrinsic->Parameters().empty() && if (builtin && !builtin->Parameters().empty() &&
intrinsic->Parameters()[0]->Type()->Is<sem::ExternalTexture>() && builtin->Parameters()[0]->Type()->Is<sem::ExternalTexture>() &&
intrinsic->Type() != sem::IntrinsicType::kTextureDimensions) { builtin->Type() != sem::BuiltinType::kTextureDimensions) {
auto it = new_binding_symbols.find( auto it = new_binding_symbols.find(
expr->args[0]->As<ast::IdentifierExpression>()->symbol); expr->args[0]->As<ast::IdentifierExpression>()->symbol);
if (it == new_binding_symbols.end()) { if (it == new_binding_symbols.end()) {
@ -164,11 +164,11 @@ struct MultiplanarExternalTexture::State {
} }
auto& syms = it->second; auto& syms = it->second;
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad) { if (builtin->Type() == sem::BuiltinType::kTextureLoad) {
return createTexLdExt(expr, syms); return createTexLdExt(expr, syms);
} }
if (intrinsic->Type() == sem::IntrinsicType::kTextureSampleLevel) { if (builtin->Type() == sem::BuiltinType::kTextureSampleLevel) {
return createTexSmpExt(expr, syms); return createTexSmpExt(expr, syms);
} }
@ -248,12 +248,12 @@ struct MultiplanarExternalTexture::State {
/// bodies of the textureSampleExternal and textureLoadExternal functions. /// bodies of the textureSampleExternal and textureLoadExternal functions.
/// @param call_type determines which function body to generate /// @param call_type determines which function body to generate
/// @returns a statement list that makes of the body of the chosen function /// @returns a statement list that makes of the body of the chosen function
ast::StatementList createTexFnExtStatementList(sem::IntrinsicType call_type) { ast::StatementList createTexFnExtStatementList(sem::BuiltinType call_type) {
using f32 = ProgramBuilder::f32; using f32 = ProgramBuilder::f32;
const ast::CallExpression* single_plane_call = nullptr; const ast::CallExpression* single_plane_call = nullptr;
const ast::CallExpression* plane_0_call = nullptr; const ast::CallExpression* plane_0_call = nullptr;
const ast::CallExpression* plane_1_call = nullptr; const ast::CallExpression* plane_1_call = nullptr;
if (call_type == sem::IntrinsicType::kTextureSampleLevel) { if (call_type == sem::BuiltinType::kTextureSampleLevel) {
// textureSampleLevel(plane0, smp, coord.xy, 0.0); // textureSampleLevel(plane0, smp, coord.xy, 0.0);
single_plane_call = single_plane_call =
b.Call("textureSampleLevel", "plane0", "smp", "coord", 0.0f); b.Call("textureSampleLevel", "plane0", "smp", "coord", 0.0f);
@ -263,7 +263,7 @@ struct MultiplanarExternalTexture::State {
// textureSampleLevel(plane1, smp, coord.xy, 0.0); // textureSampleLevel(plane1, smp, coord.xy, 0.0);
plane_1_call = plane_1_call =
b.Call("textureSampleLevel", "plane1", "smp", "coord", 0.0f); b.Call("textureSampleLevel", "plane1", "smp", "coord", 0.0f);
} else if (call_type == sem::IntrinsicType::kTextureLoad) { } else if (call_type == sem::BuiltinType::kTextureLoad) {
// textureLoad(plane0, coords.xy, 0); // textureLoad(plane0, coords.xy, 0);
single_plane_call = b.Call("textureLoad", "plane0", "coord", 0); single_plane_call = b.Call("textureLoad", "plane0", "coord", 0);
// textureLoad(plane0, coords.xy, 0); // textureLoad(plane0, coords.xy, 0);
@ -272,7 +272,7 @@ struct MultiplanarExternalTexture::State {
plane_1_call = b.Call("textureLoad", "plane1", "coord", 0); plane_1_call = b.Call("textureLoad", "plane1", "coord", 0);
} else { } else {
TINT_ICE(Transform, b.Diagnostics()) TINT_ICE(Transform, b.Diagnostics())
<< "unhandled intrinsic: " << call_type; << "unhandled builtin: " << call_type;
} }
return { return {
@ -343,7 +343,7 @@ struct MultiplanarExternalTexture::State {
b.Param("params", b.ty.type_name(params_struct_sym))}; b.Param("params", b.ty.type_name(params_struct_sym))};
ast::StatementList statementList = ast::StatementList statementList =
createTexFnExtStatementList(sem::IntrinsicType::kTextureSampleLevel); createTexFnExtStatementList(sem::BuiltinType::kTextureSampleLevel);
b.Func(texture_sample_external_sym, varList, b.ty.vec4(b.ty.f32()), b.Func(texture_sample_external_sym, varList, b.ty.vec4(b.ty.f32()),
statementList, {}); statementList, {});
@ -386,7 +386,7 @@ struct MultiplanarExternalTexture::State {
b.Param("params", b.ty.type_name(params_struct_sym))}; b.Param("params", b.ty.type_name(params_struct_sym))};
ast::StatementList statement_list = ast::StatementList statement_list =
createTexFnExtStatementList(sem::IntrinsicType::kTextureLoad); createTexFnExtStatementList(sem::BuiltinType::kTextureLoad);
b.Func(texture_load_external_sym, var_list, b.ty.vec4(b.ty.f32()), b.Func(texture_load_external_sym, var_list, b.ty.vec4(b.ty.f32()),
statement_list, {}); statement_list, {});

View File

@ -20,7 +20,7 @@
#include "src/ast/struct_member.h" #include "src/ast/struct_member.h"
#include "src/sem/binding_point.h" #include "src/sem/binding_point.h"
#include "src/sem/intrinsic_type.h" #include "src/sem/builtin_type.h"
#include "src/transform/transform.h" #include "src/transform/transform.h"
namespace tint { namespace tint {

View File

@ -89,12 +89,12 @@ void RemovePhonies::Run(CloneContext& ctx, const DataMap&, DataMap&) const {
if (!ast::TraverseExpressions( if (!ast::TraverseExpressions(
stmt->rhs, ctx.dst->Diagnostics(), stmt->rhs, ctx.dst->Diagnostics(),
[&](const ast::CallExpression* call) { [&](const ast::CallExpression* call) {
// ast::CallExpression may map to a function or intrinsic call // ast::CallExpression may map to a function or builtin call
// (both may have side-effects), or a type constructor or // (both may have side-effects), or a type constructor or
// type conversion (both do not have side effects). // type conversion (both do not have side effects).
if (sem.Get(call) if (sem.Get(call)
->Target() ->Target()
->IsAnyOf<sem::Function, sem::Intrinsic>()) { ->IsAnyOf<sem::Function, sem::Builtin>()) {
side_effects.push_back(call); side_effects.push_back(call);
return ast::TraverseAction::Skip; return ast::TraverseAction::Skip;
} }

View File

@ -1257,7 +1257,7 @@ Output Renamer::Run(const Program* in, const DataMap& inputs) const {
// Disable auto-cloning of symbols, since we want to rename them. // Disable auto-cloning of symbols, since we want to rename them.
CloneContext ctx(&out, in, false); CloneContext ctx(&out, in, false);
// Swizzles, intrinsic calls and builtin structure members need to keep their // Swizzles, builtin calls and builtin structure members need to keep their
// symbols preserved. // symbols preserved.
std::unordered_set<const ast::IdentifierExpression*> preserve; std::unordered_set<const ast::IdentifierExpression*> preserve;
for (auto* node : in->ASTNodes().Objects()) { for (auto* node : in->ASTNodes().Objects()) {
@ -1284,7 +1284,7 @@ Output Renamer::Run(const Program* in, const DataMap& inputs) const {
<< "CallExpression has no semantic info"; << "CallExpression has no semantic info";
continue; continue;
} }
if (sem->Target()->Is<sem::Intrinsic>()) { if (sem->Target()->Is<sem::Builtin>()) {
preserve.emplace(call->target.name); preserve.emplace(call->target.name);
} }
} }

View File

@ -118,7 +118,7 @@ fn tint_symbol() -> @builtin(position) vec4<f32> {
EXPECT_THAT(data->remappings, ContainerEq(expected_remappings)); EXPECT_THAT(data->remappings, ContainerEq(expected_remappings));
} }
TEST_F(RenamerTest, PreserveIntrinsics) { TEST_F(RenamerTest, PreserveBuiltins) {
auto* src = R"( auto* src = R"(
@stage(vertex) @stage(vertex)
fn entry() -> @builtin(position) vec4<f32> { fn entry() -> @builtin(position) vec4<f32> {
@ -666,20 +666,20 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
"VPOS", "VPOS",
"VertexShader", "VertexShader",
"abort", "abort",
// "abs", // WGSL intrinsic // "abs", // WGSL builtin
// "acos", // WGSL intrinsic // "acos", // WGSL builtin
// "all", // WGSL intrinsic // "all", // WGSL builtin
"allow_uav_condition", "allow_uav_condition",
// "any", // WGSL intrinsic // "any", // WGSL builtin
"asdouble", "asdouble",
"asfloat", "asfloat",
// "asin", // WGSL intrinsic // "asin", // WGSL builtin
"asint", "asint",
// "asm", // WGSL keyword // "asm", // WGSL keyword
"asm_fragment", "asm_fragment",
"asuint", "asuint",
// "atan", // WGSL intrinsic // "atan", // WGSL builtin
// "atan2", // WGSL intrinsic // "atan2", // WGSL builtin
"auto", "auto",
// "bool", // WGSL keyword // "bool", // WGSL keyword
"bool1", "bool1",
@ -704,14 +704,14 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
"bool4x4", "bool4x4",
"branch", "branch",
// "break", // WGSL keyword // "break", // WGSL keyword
// "call", // WGSL intrinsic // "call", // WGSL builtin
// "case", // WGSL keyword // "case", // WGSL keyword
"catch", "catch",
"cbuffer", "cbuffer",
// "ceil", // WGSL intrinsic // "ceil", // WGSL builtin
"centroid", "centroid",
"char", "char",
// "clamp", // WGSL intrinsic // "clamp", // WGSL builtin
"class", "class",
"clip", "clip",
"column_major", "column_major",
@ -720,10 +720,10 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
// "const", // WGSL keyword // "const", // WGSL keyword
"const_cast", "const_cast",
// "continue", // WGSL keyword // "continue", // WGSL keyword
// "cos", // WGSL intrinsic // "cos", // WGSL builtin
// "cosh", // WGSL intrinsic // "cosh", // WGSL builtin
"countbits", "countbits",
// "cross", // WGSL intrinsic // "cross", // WGSL builtin
"ddx", "ddx",
"ddx_coarse", "ddx_coarse",
"ddx_fine", "ddx_fine",
@ -733,11 +733,11 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
// "default", // WGSL keyword // "default", // WGSL keyword
"degrees", "degrees",
"delete", "delete",
// "determinant", // WGSL intrinsic // "determinant", // WGSL builtin
// "discard", // WGSL keyword // "discard", // WGSL keyword
// "distance", // WGSL intrinsic // "distance", // WGSL builtin
// "do", // WGSL keyword // "do", // WGSL keyword
// "dot", // WGSL intrinsic // "dot", // WGSL builtin
"double", "double",
"double1", "double1",
"double1x1", "double1x1",
@ -785,14 +785,14 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
// "else", // WGSL keyword // "else", // WGSL keyword
// "enum", // WGSL keyword // "enum", // WGSL keyword
"errorf", "errorf",
// "exp", // WGSL intrinsic // "exp", // WGSL builtin
// "exp2", // WGSL intrinsic // "exp2", // WGSL builtin
"explicit", "explicit",
"export", "export",
"extern", "extern",
"f16to32", "f16to32",
"f32tof16", "f32tof16",
// "faceforward", // WGSL intrinsic // "faceforward", // WGSL builtin
// "false", // WGSL keyword // "false", // WGSL keyword
"fastopt", "fastopt",
"firstbithigh", "firstbithigh",
@ -819,15 +819,15 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
"float4x2", "float4x2",
"float4x3", "float4x3",
"float4x4", "float4x4",
// "floor", // WGSL intrinsic // "floor", // WGSL builtin
// "fma", // WGSL intrinsic // "fma", // WGSL builtin
"fmod", "fmod",
// "for", // WGSL keyword // "for", // WGSL keyword
"forcecase", "forcecase",
"frac", "frac",
// "frexp", // WGSL intrinsic // "frexp", // WGSL builtin
"friend", "friend",
// "fwidth", // WGSL intrinsic // "fwidth", // WGSL builtin
"fxgroup", "fxgroup",
"goto", "goto",
"groupshared", "groupshared",
@ -881,22 +881,22 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
"isfinite", "isfinite",
"isinf", "isinf",
"isnan", "isnan",
// "ldexp", // WGSL intrinsic // "ldexp", // WGSL builtin
// "length", // WGSL intrinsic // "length", // WGSL builtin
"lerp", "lerp",
"line", "line",
"lineadj", "lineadj",
"linear", "linear",
"lit", "lit",
// "log", // WGSL intrinsic // "log", // WGSL builtin
"log10", "log10",
// "log2", // WGSL intrinsic // "log2", // WGSL builtin
"long", "long",
// "loop", // WGSL keyword // "loop", // WGSL keyword
"mad", "mad",
"matrix", "matrix",
// "max", // WGSL intrinsic // "max", // WGSL builtin
// "min", // WGSL intrinsic // "min", // WGSL builtin
"min10float", "min10float",
"min10float1", "min10float1",
"min10float1x1", "min10float1x1",
@ -1002,7 +1002,7 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
"min16uint4x2", "min16uint4x2",
"min16uint4x3", "min16uint4x3",
"min16uint4x4", "min16uint4x4",
// "modf", // WGSL intrinsic // "modf", // WGSL builtin
"msad4", "msad4",
"mul", "mul",
"mutable", "mutable",
@ -1011,7 +1011,7 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
"nointerpolation", "nointerpolation",
"noise", "noise",
"noperspective", "noperspective",
// "normalize", // WGSL intrinsic // "normalize", // WGSL builtin
"numthreads", "numthreads",
"operator", "operator",
// "out", // WGSL keyword // "out", // WGSL keyword
@ -1020,7 +1020,7 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
"pixelfragment", "pixelfragment",
"pixelshader", "pixelshader",
"point", "point",
// "pow", // WGSL intrinsic // "pow", // WGSL builtin
"precise", "precise",
"printf", "printf",
// "private", // WGSL keyword // "private", // WGSL keyword
@ -1028,13 +1028,13 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
"public", "public",
"radians", "radians",
"rcp", "rcp",
// "reflect", // WGSL intrinsic // "reflect", // WGSL builtin
"refract", "refract",
"register", "register",
"reinterpret_cast", "reinterpret_cast",
// "return", // WGSL keyword // "return", // WGSL keyword
// "reversebits", // WGSL intrinsic // "reversebits", // WGSL builtin
// "round", // WGSL intrinsic // "round", // WGSL builtin
"row_major", "row_major",
"rsqrt", "rsqrt",
"sample", "sample",
@ -1046,25 +1046,25 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
"saturate", "saturate",
"shared", "shared",
"short", "short",
// "sign", // WGSL intrinsic // "sign", // WGSL builtin
"signed", "signed",
// "sin", // WGSL intrinsic // "sin", // WGSL builtin
"sincos", "sincos",
// "sinh", // WGSL intrinsic // "sinh", // WGSL builtin
"sizeof", "sizeof",
// "smoothstep", // WGSL intrinsic // "smoothstep", // WGSL builtin
"snorm", "snorm",
// "sqrt", // WGSL intrinsic // "sqrt", // WGSL builtin
"stateblock", "stateblock",
"stateblock_state", "stateblock_state",
"static", "static",
"static_cast", "static_cast",
// "step", // WGSL intrinsic // "step", // WGSL builtin
"string", "string",
// "struct", // WGSL keyword // "struct", // WGSL keyword
// "switch", // WGSL keyword // "switch", // WGSL keyword
// "tan", // WGSL intrinsic // "tan", // WGSL builtin
// "tanh", // WGSL intrinsic // "tanh", // WGSL builtin
"tbuffer", "tbuffer",
"technique", "technique",
"technique10", "technique10",
@ -1106,7 +1106,7 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
"triangle", "triangle",
"triangleadj", "triangleadj",
// "true", // WGSL keyword // "true", // WGSL keyword
// "trunc", // WGSL intrinsic // "trunc", // WGSL builtin
"try", "try",
// "typedef", // WGSL keyword // "typedef", // WGSL keyword
"typename", "typename",

View File

@ -200,24 +200,24 @@ struct Robustness::State {
return b.IndexAccessor(src, obj, idx.expr); return b.IndexAccessor(src, obj, idx.expr);
} }
/// @param type intrinsic type /// @param type builtin type
/// @returns true if the given intrinsic is a texture function that requires /// @returns true if the given builtin is a texture function that requires
/// argument clamping, /// argument clamping,
bool TextureIntrinsicNeedsClamping(sem::IntrinsicType type) { bool TextureBuiltinNeedsClamping(sem::BuiltinType type) {
return type == sem::IntrinsicType::kTextureLoad || return type == sem::BuiltinType::kTextureLoad ||
type == sem::IntrinsicType::kTextureStore; type == sem::BuiltinType::kTextureStore;
} }
/// Apply bounds clamping to the coordinates, array index and level arguments /// Apply bounds clamping to the coordinates, array index and level arguments
/// of the `textureLoad()` and `textureStore()` intrinsics. /// of the `textureLoad()` and `textureStore()` builtins.
/// @param expr the intrinsic call expression /// @param expr the builtin call expression
/// @return the clamped replacement call expression, or nullptr if `expr` /// @return the clamped replacement call expression, or nullptr if `expr`
/// should be cloned without changes. /// should be cloned without changes.
const ast::CallExpression* Transform(const ast::CallExpression* expr) { const ast::CallExpression* Transform(const ast::CallExpression* expr) {
auto* call = ctx.src->Sem().Get(expr); auto* call = ctx.src->Sem().Get(expr);
auto* call_target = call->Target(); auto* call_target = call->Target();
auto* intrinsic = call_target->As<sem::Intrinsic>(); auto* builtin = call_target->As<sem::Builtin>();
if (!intrinsic || !TextureIntrinsicNeedsClamping(intrinsic->Type())) { if (!builtin || !TextureBuiltinNeedsClamping(builtin->Type())) {
return nullptr; // No transform, just clone. return nullptr; // No transform, just clone.
} }
@ -225,7 +225,7 @@ struct Robustness::State {
// Indices of the mandatory texture and coords parameters, and the optional // Indices of the mandatory texture and coords parameters, and the optional
// array and level parameters. // array and level parameters.
auto& signature = intrinsic->Signature(); auto& signature = builtin->Signature();
auto texture_idx = signature.IndexOf(sem::ParameterUsage::kTexture); auto texture_idx = signature.IndexOf(sem::ParameterUsage::kTexture);
auto coords_idx = signature.IndexOf(sem::ParameterUsage::kCoords); auto coords_idx = signature.IndexOf(sem::ParameterUsage::kCoords);
auto array_idx = signature.IndexOf(sem::ParameterUsage::kArrayIndex); auto array_idx = signature.IndexOf(sem::ParameterUsage::kArrayIndex);
@ -233,7 +233,7 @@ struct Robustness::State {
auto* texture_arg = expr->args[texture_idx]; auto* texture_arg = expr->args[texture_idx];
auto* coords_arg = expr->args[coords_idx]; auto* coords_arg = expr->args[coords_idx];
auto* coords_ty = intrinsic->Parameters()[coords_idx]->Type(); auto* coords_ty = builtin->Parameters()[coords_idx]->Type();
// If the level is provided, then we need to clamp this. As the level is // If the level is provided, then we need to clamp this. As the level is
// used by textureDimensions() and the texture[Load|Store]() calls, we need // used by textureDimensions() and the texture[Load|Store]() calls, we need

View File

@ -444,8 +444,8 @@ bool GeneratorImpl::EmitCall(std::ostream& out,
if (auto* func = target->As<sem::Function>()) { if (auto* func = target->As<sem::Function>()) {
return EmitFunctionCall(out, call, func); return EmitFunctionCall(out, call, func);
} }
if (auto* intrinsic = target->As<sem::Intrinsic>()) { if (auto* builtin = target->As<sem::Builtin>()) {
return EmitIntrinsicCall(out, call, intrinsic); return EmitBuiltinCall(out, call, builtin);
} }
if (auto* cast = target->As<sem::TypeConversion>()) { if (auto* cast = target->As<sem::TypeConversion>()) {
return EmitTypeConversion(out, call, cast); return EmitTypeConversion(out, call, cast);
@ -501,47 +501,47 @@ bool GeneratorImpl::EmitFunctionCall(std::ostream& out,
return true; return true;
} }
bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out, bool GeneratorImpl::EmitBuiltinCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
auto* expr = call->Declaration(); auto* expr = call->Declaration();
if (intrinsic->IsTexture()) { if (builtin->IsTexture()) {
return EmitTextureCall(out, call, intrinsic); return EmitTextureCall(out, call, builtin);
} }
if (intrinsic->Type() == sem::IntrinsicType::kSelect) { if (builtin->Type() == sem::BuiltinType::kSelect) {
return EmitSelectCall(out, expr); return EmitSelectCall(out, expr);
} }
if (intrinsic->Type() == sem::IntrinsicType::kDot) { if (builtin->Type() == sem::BuiltinType::kDot) {
return EmitDotCall(out, expr, intrinsic); return EmitDotCall(out, expr, builtin);
} }
if (intrinsic->Type() == sem::IntrinsicType::kModf) { if (builtin->Type() == sem::BuiltinType::kModf) {
return EmitModfCall(out, expr, intrinsic); return EmitModfCall(out, expr, builtin);
} }
if (intrinsic->Type() == sem::IntrinsicType::kFrexp) { if (builtin->Type() == sem::BuiltinType::kFrexp) {
return EmitFrexpCall(out, expr, intrinsic); return EmitFrexpCall(out, expr, builtin);
} }
if (intrinsic->Type() == sem::IntrinsicType::kIsNormal) { if (builtin->Type() == sem::BuiltinType::kIsNormal) {
return EmitIsNormalCall(out, expr, intrinsic); return EmitIsNormalCall(out, expr, builtin);
} }
if (intrinsic->Type() == sem::IntrinsicType::kDegrees) { if (builtin->Type() == sem::BuiltinType::kDegrees) {
return EmitDegreesCall(out, expr, intrinsic); return EmitDegreesCall(out, expr, builtin);
} }
if (intrinsic->Type() == sem::IntrinsicType::kRadians) { if (builtin->Type() == sem::BuiltinType::kRadians) {
return EmitRadiansCall(out, expr, intrinsic); return EmitRadiansCall(out, expr, builtin);
} }
if (intrinsic->IsDataPacking()) { if (builtin->IsDataPacking()) {
return EmitDataPackingCall(out, expr, intrinsic); return EmitDataPackingCall(out, expr, builtin);
} }
if (intrinsic->IsDataUnpacking()) { if (builtin->IsDataUnpacking()) {
return EmitDataUnpackingCall(out, expr, intrinsic); return EmitDataUnpackingCall(out, expr, builtin);
} }
if (intrinsic->IsBarrier()) { if (builtin->IsBarrier()) {
return EmitBarrierCall(out, intrinsic); return EmitBarrierCall(out, builtin);
} }
if (intrinsic->IsAtomic()) { if (builtin->IsAtomic()) {
return EmitWorkgroupAtomicCall(out, expr, intrinsic); return EmitWorkgroupAtomicCall(out, expr, builtin);
} }
auto name = generate_builtin_name(intrinsic); auto name = generate_builtin_name(builtin);
if (name.empty()) { if (name.empty()) {
return false; return false;
} }
@ -621,7 +621,7 @@ bool GeneratorImpl::EmitTypeConstructor(std::ostream& out,
bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out, bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
auto call = [&](const char* name) { auto call = [&](const char* name) {
out << name; out << name;
{ {
@ -639,8 +639,8 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
return true; return true;
}; };
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kAtomicLoad: { case sem::BuiltinType::kAtomicLoad: {
// GLSL does not have an atomicLoad, so we emulate it with // GLSL does not have an atomicLoad, so we emulate it with
// atomicOr using 0 as the OR value // atomicOr using 0 as the OR value
out << "atomicOr"; out << "atomicOr";
@ -650,19 +650,19 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
return false; return false;
} }
out << ", 0"; out << ", 0";
if (intrinsic->ReturnType()->Is<sem::U32>()) { if (builtin->ReturnType()->Is<sem::U32>()) {
out << "u"; out << "u";
} }
} }
return true; return true;
} }
case sem::IntrinsicType::kAtomicCompareExchangeWeak: { case sem::BuiltinType::kAtomicCompareExchangeWeak: {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
{ {
auto pre = line(b); auto pre = line(b);
if (!EmitTypeAndName(pre, intrinsic->ReturnType(), if (!EmitTypeAndName(pre, builtin->ReturnType(),
ast::StorageClass::kNone, ast::StorageClass::kNone,
ast::Access::kUndefined, "result")) { ast::Access::kUndefined, "result")) {
return false; return false;
@ -694,27 +694,27 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
}); });
} }
case sem::IntrinsicType::kAtomicAdd: case sem::BuiltinType::kAtomicAdd:
case sem::IntrinsicType::kAtomicSub: case sem::BuiltinType::kAtomicSub:
return call("atomicAdd"); return call("atomicAdd");
case sem::IntrinsicType::kAtomicMax: case sem::BuiltinType::kAtomicMax:
return call("atomicMax"); return call("atomicMax");
case sem::IntrinsicType::kAtomicMin: case sem::BuiltinType::kAtomicMin:
return call("atomicMin"); return call("atomicMin");
case sem::IntrinsicType::kAtomicAnd: case sem::BuiltinType::kAtomicAnd:
return call("atomicAnd"); return call("atomicAnd");
case sem::IntrinsicType::kAtomicOr: case sem::BuiltinType::kAtomicOr:
return call("atomicOr"); return call("atomicOr");
case sem::IntrinsicType::kAtomicXor: case sem::BuiltinType::kAtomicXor:
return call("atomicXor"); return call("atomicXor");
case sem::IntrinsicType::kAtomicExchange: case sem::BuiltinType::kAtomicExchange:
case sem::IntrinsicType::kAtomicStore: case sem::BuiltinType::kAtomicStore:
// GLSL does not have an atomicStore, so we emulate it with // GLSL does not have an atomicStore, so we emulate it with
// atomicExchange. // atomicExchange.
return call("atomicExchange"); return call("atomicExchange");
@ -724,7 +724,7 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
} }
TINT_UNREACHABLE(Writer, diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported atomic intrinsic: " << intrinsic->Type(); << "unsupported atomic builtin: " << builtin->Type();
return false; return false;
} }
@ -755,8 +755,8 @@ bool GeneratorImpl::EmitSelectCall(std::ostream& out,
bool GeneratorImpl::EmitDotCall(std::ostream& out, bool GeneratorImpl::EmitDotCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
auto* vec_ty = intrinsic->Parameters()[0]->Type()->As<sem::Vector>(); auto* vec_ty = builtin->Parameters()[0]->Type()->As<sem::Vector>();
std::string fn = "dot"; std::string fn = "dot";
if (vec_ty->type()->is_integer_scalar()) { if (vec_ty->type()->is_integer_scalar()) {
// GLSL does not have a builtin for dot() with integer vector types. // GLSL does not have a builtin for dot() with integer vector types.
@ -827,12 +827,12 @@ bool GeneratorImpl::EmitDotCall(std::ostream& out,
bool GeneratorImpl::EmitModfCall(std::ostream& out, bool GeneratorImpl::EmitModfCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
if (expr->args.size() == 1) { if (expr->args.size() == 1) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
auto* ty = intrinsic->Parameters()[0]->Type(); auto* ty = builtin->Parameters()[0]->Type();
auto in = params[0]; auto in = params[0];
std::string width; std::string width;
@ -843,7 +843,7 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
// Emit the builtin return type unique to this overload. This does not // Emit the builtin return type unique to this overload. This does not
// exist in the AST, so it will not be generated in Generate(). // exist in the AST, so it will not be generated in Generate().
if (!EmitStructType(&helpers_, if (!EmitStructType(&helpers_,
intrinsic->ReturnType()->As<sem::Struct>())) { builtin->ReturnType()->As<sem::Struct>())) {
return false; return false;
} }
@ -851,7 +851,7 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
line(b) << "float" << width << " fract = modf(" << in << ", whole);"; line(b) << "float" << width << " fract = modf(" << in << ", whole);";
{ {
auto l = line(b); auto l = line(b);
if (!EmitType(l, intrinsic->ReturnType(), ast::StorageClass::kNone, if (!EmitType(l, builtin->ReturnType(), ast::StorageClass::kNone,
ast::Access::kUndefined, "")) { ast::Access::kUndefined, "")) {
return false; return false;
} }
@ -877,12 +877,12 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
bool GeneratorImpl::EmitFrexpCall(std::ostream& out, bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
if (expr->args.size() == 1) { if (expr->args.size() == 1) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
auto* ty = intrinsic->Parameters()[0]->Type(); auto* ty = builtin->Parameters()[0]->Type();
auto in = params[0]; auto in = params[0];
std::string width; std::string width;
@ -893,7 +893,7 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
// Emit the builtin return type unique to this overload. This does not // Emit the builtin return type unique to this overload. This does not
// exist in the AST, so it will not be generated in Generate(). // exist in the AST, so it will not be generated in Generate().
if (!EmitStructType(&helpers_, if (!EmitStructType(&helpers_,
intrinsic->ReturnType()->As<sem::Struct>())) { builtin->ReturnType()->As<sem::Struct>())) {
return false; return false;
} }
@ -901,7 +901,7 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
line(b) << "float" << width << " sig = frexp(" << in << ", exp);"; line(b) << "float" << width << " sig = frexp(" << in << ", exp);";
{ {
auto l = line(b); auto l = line(b);
if (!EmitType(l, intrinsic->ReturnType(), ast::StorageClass::kNone, if (!EmitType(l, builtin->ReturnType(), ast::StorageClass::kNone,
ast::Access::kUndefined, "")) { ast::Access::kUndefined, "")) {
return false; return false;
} }
@ -914,12 +914,12 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
// DEPRECATED // DEPRECATED
// Exponent is an integer in WGSL, but HLSL wants a float. // Exponent is an integer in WGSL, but HLSL wants a float.
// We need to make the call with a temporary float, and then cast. // We need to make the call with a temporary float, and then cast.
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
auto* significand_ty = intrinsic->Parameters()[0]->Type(); auto* significand_ty = builtin->Parameters()[0]->Type();
auto significand = params[0]; auto significand = params[0];
auto* exponent_ty = intrinsic->Parameters()[1]->Type(); auto* exponent_ty = builtin->Parameters()[1]->Type();
auto exponent = params[1]; auto exponent = params[1];
std::string width; std::string width;
@ -948,12 +948,12 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
bool GeneratorImpl::EmitIsNormalCall(std::ostream& out, bool GeneratorImpl::EmitIsNormalCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
// GLSL doesn't have a isNormal intrinsic, we need to emulate // GLSL doesn't have a isNormal builtin, we need to emulate
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
auto* input_ty = intrinsic->Parameters()[0]->Type(); auto* input_ty = builtin->Parameters()[0]->Type();
std::string width; std::string width;
if (auto* vec = input_ty->As<sem::Vector>()) { if (auto* vec = input_ty->As<sem::Vector>()) {
@ -976,9 +976,9 @@ bool GeneratorImpl::EmitIsNormalCall(std::ostream& out,
bool GeneratorImpl::EmitDegreesCall(std::ostream& out, bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
line(b) << "return " << params[0] << " * " << std::setprecision(20) line(b) << "return " << params[0] << " * " << std::setprecision(20)
<< sem::kRadToDeg << ";"; << sem::kRadToDeg << ";";
@ -988,9 +988,9 @@ bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
bool GeneratorImpl::EmitRadiansCall(std::ostream& out, bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
line(b) << "return " << params[0] << " * " << std::setprecision(20) line(b) << "return " << params[0] << " * " << std::setprecision(20)
<< sem::kDegToRad << ";"; << sem::kDegToRad << ";";
@ -1000,28 +1000,28 @@ bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
bool GeneratorImpl::EmitDataPackingCall(std::ostream& out, bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
uint32_t dims = 2; uint32_t dims = 2;
bool is_signed = false; bool is_signed = false;
uint32_t scale = 65535; uint32_t scale = 65535;
if (intrinsic->Type() == sem::IntrinsicType::kPack4x8snorm || if (builtin->Type() == sem::BuiltinType::kPack4x8snorm ||
intrinsic->Type() == sem::IntrinsicType::kPack4x8unorm) { builtin->Type() == sem::BuiltinType::kPack4x8unorm) {
dims = 4; dims = 4;
scale = 255; scale = 255;
} }
if (intrinsic->Type() == sem::IntrinsicType::kPack4x8snorm || if (builtin->Type() == sem::BuiltinType::kPack4x8snorm ||
intrinsic->Type() == sem::IntrinsicType::kPack2x16snorm) { builtin->Type() == sem::BuiltinType::kPack2x16snorm) {
is_signed = true; is_signed = true;
scale = (scale - 1) / 2; scale = (scale - 1) / 2;
} }
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kPack4x8snorm: case sem::BuiltinType::kPack4x8snorm:
case sem::IntrinsicType::kPack4x8unorm: case sem::BuiltinType::kPack4x8unorm:
case sem::IntrinsicType::kPack2x16snorm: case sem::BuiltinType::kPack2x16snorm:
case sem::IntrinsicType::kPack2x16unorm: { case sem::BuiltinType::kPack2x16unorm: {
{ {
auto l = line(b); auto l = line(b);
l << (is_signed ? "" : "u") << "int" << dims l << (is_signed ? "" : "u") << "int" << dims
@ -1048,7 +1048,7 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
} }
break; break;
} }
case sem::IntrinsicType::kPack2x16float: { case sem::BuiltinType::kPack2x16float: {
line(b) << "uint2 i = f32tof16(" << params[0] << ");"; line(b) << "uint2 i = f32tof16(" << params[0] << ");";
line(b) << "return i.x | (i.y << 16);"; line(b) << "return i.x | (i.y << 16);";
break; break;
@ -1056,7 +1056,7 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
default: default:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer, diag::System::Writer,
"Internal error: unhandled data packing intrinsic"); "Internal error: unhandled data packing builtin");
return false; return false;
} }
@ -1066,26 +1066,26 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out, bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
uint32_t dims = 2; uint32_t dims = 2;
bool is_signed = false; bool is_signed = false;
uint32_t scale = 65535; uint32_t scale = 65535;
if (intrinsic->Type() == sem::IntrinsicType::kUnpack4x8snorm || if (builtin->Type() == sem::BuiltinType::kUnpack4x8snorm ||
intrinsic->Type() == sem::IntrinsicType::kUnpack4x8unorm) { builtin->Type() == sem::BuiltinType::kUnpack4x8unorm) {
dims = 4; dims = 4;
scale = 255; scale = 255;
} }
if (intrinsic->Type() == sem::IntrinsicType::kUnpack4x8snorm || if (builtin->Type() == sem::BuiltinType::kUnpack4x8snorm ||
intrinsic->Type() == sem::IntrinsicType::kUnpack2x16snorm) { builtin->Type() == sem::BuiltinType::kUnpack2x16snorm) {
is_signed = true; is_signed = true;
scale = (scale - 1) / 2; scale = (scale - 1) / 2;
} }
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kUnpack4x8snorm: case sem::BuiltinType::kUnpack4x8snorm:
case sem::IntrinsicType::kUnpack2x16snorm: { case sem::BuiltinType::kUnpack2x16snorm: {
line(b) << "int j = int(" << params[0] << ");"; line(b) << "int j = int(" << params[0] << ");";
{ // Perform sign extension on the converted values. { // Perform sign extension on the converted values.
auto l = line(b); auto l = line(b);
@ -1101,8 +1101,8 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
<< ".0, " << (is_signed ? "-1.0" : "0.0") << ", 1.0);"; << ".0, " << (is_signed ? "-1.0" : "0.0") << ", 1.0);";
break; break;
} }
case sem::IntrinsicType::kUnpack4x8unorm: case sem::BuiltinType::kUnpack4x8unorm:
case sem::IntrinsicType::kUnpack2x16unorm: { case sem::BuiltinType::kUnpack2x16unorm: {
line(b) << "uint j = " << params[0] << ";"; line(b) << "uint j = " << params[0] << ";";
{ {
auto l = line(b); auto l = line(b);
@ -1119,14 +1119,14 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
line(b) << "return float" << dims << "(i) / " << scale << ".0;"; line(b) << "return float" << dims << "(i) / " << scale << ".0;";
break; break;
} }
case sem::IntrinsicType::kUnpack2x16float: case sem::BuiltinType::kUnpack2x16float:
line(b) << "uint i = " << params[0] << ";"; line(b) << "uint i = " << params[0] << ";";
line(b) << "return f16tof32(uint2(i & 0xffff, i >> 16));"; line(b) << "return f16tof32(uint2(i & 0xffff, i >> 16));";
break; break;
default: default:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer, diag::System::Writer,
"Internal error: unhandled data packing intrinsic"); "Internal error: unhandled data packing builtin");
return false; return false;
} }
@ -1135,16 +1135,16 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
} }
bool GeneratorImpl::EmitBarrierCall(std::ostream& out, bool GeneratorImpl::EmitBarrierCall(std::ostream& out,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
// TODO(crbug.com/tint/661): Combine sequential barriers to a single // TODO(crbug.com/tint/661): Combine sequential barriers to a single
// instruction. // instruction.
if (intrinsic->Type() == sem::IntrinsicType::kWorkgroupBarrier) { if (builtin->Type() == sem::BuiltinType::kWorkgroupBarrier) {
out << "memoryBarrierShared()"; out << "memoryBarrierShared()";
} else if (intrinsic->Type() == sem::IntrinsicType::kStorageBarrier) { } else if (builtin->Type() == sem::BuiltinType::kStorageBarrier) {
out << "memoryBarrierBuffer()"; out << "memoryBarrierBuffer()";
} else { } else {
TINT_UNREACHABLE(Writer, diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unexpected barrier intrinsic type " << sem::str(intrinsic->Type()); << "unexpected barrier builtin type " << sem::str(builtin->Type());
return false; return false;
} }
return true; return true;
@ -1152,10 +1152,10 @@ bool GeneratorImpl::EmitBarrierCall(std::ostream& out,
bool GeneratorImpl::EmitTextureCall(std::ostream& out, bool GeneratorImpl::EmitTextureCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
using Usage = sem::ParameterUsage; using Usage = sem::ParameterUsage;
auto& signature = intrinsic->Signature(); auto& signature = builtin->Signature();
auto* expr = call->Declaration(); auto* expr = call->Declaration();
auto arguments = expr->args; auto arguments = expr->args;
@ -1173,8 +1173,8 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
auto* texture_type = TypeOf(texture)->UnwrapRef()->As<sem::Texture>(); auto* texture_type = TypeOf(texture)->UnwrapRef()->As<sem::Texture>();
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kTextureDimensions: { case sem::BuiltinType::kTextureDimensions: {
if (texture_type->Is<sem::StorageTexture>()) { if (texture_type->Is<sem::StorageTexture>()) {
out << "imageSize("; out << "imageSize(";
} else { } else {
@ -1207,8 +1207,8 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
return true; return true;
} }
// TODO(senorblanco): determine if this works for array textures // TODO(senorblanco): determine if this works for array textures
case sem::IntrinsicType::kTextureNumLayers: case sem::BuiltinType::kTextureNumLayers:
case sem::IntrinsicType::kTextureNumLevels: { case sem::BuiltinType::kTextureNumLevels: {
out << "textureQueryLevels("; out << "textureQueryLevels(";
if (!EmitExpression(out, texture)) { if (!EmitExpression(out, texture)) {
return false; return false;
@ -1216,7 +1216,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
out << ");"; out << ");";
return true; return true;
} }
case sem::IntrinsicType::kTextureNumSamples: { case sem::BuiltinType::kTextureNumSamples: {
out << "textureSamples("; out << "textureSamples(";
if (!EmitExpression(out, texture)) { if (!EmitExpression(out, texture)) {
return false; return false;
@ -1231,44 +1231,44 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
uint32_t glsl_ret_width = 4u; uint32_t glsl_ret_width = 4u;
bool is_depth = texture_type->Is<sem::DepthTexture>(); bool is_depth = texture_type->Is<sem::DepthTexture>();
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kTextureSample: case sem::BuiltinType::kTextureSample:
case sem::IntrinsicType::kTextureSampleBias: case sem::BuiltinType::kTextureSampleBias:
out << "texture"; out << "texture";
if (is_depth) { if (is_depth) {
glsl_ret_width = 1u; glsl_ret_width = 1u;
} }
break; break;
case sem::IntrinsicType::kTextureSampleLevel: case sem::BuiltinType::kTextureSampleLevel:
out << "textureLod"; out << "textureLod";
break; break;
case sem::IntrinsicType::kTextureGather: case sem::BuiltinType::kTextureGather:
case sem::IntrinsicType::kTextureGatherCompare: case sem::BuiltinType::kTextureGatherCompare:
out << "textureGather"; out << "textureGather";
break; break;
case sem::IntrinsicType::kTextureSampleGrad: case sem::BuiltinType::kTextureSampleGrad:
out << "textureGrad"; out << "textureGrad";
break; break;
case sem::IntrinsicType::kTextureSampleCompare: case sem::BuiltinType::kTextureSampleCompare:
case sem::IntrinsicType::kTextureSampleCompareLevel: case sem::BuiltinType::kTextureSampleCompareLevel:
out << "texture"; out << "texture";
glsl_ret_width = 1; glsl_ret_width = 1;
break; break;
case sem::IntrinsicType::kTextureLoad: case sem::BuiltinType::kTextureLoad:
out << "texelFetch"; out << "texelFetch";
break; break;
case sem::IntrinsicType::kTextureStore: case sem::BuiltinType::kTextureStore:
out << "imageStore"; out << "imageStore";
break; break;
default: default:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer, diag::System::Writer,
"Internal compiler error: Unhandled texture intrinsic '" + "Internal compiler error: Unhandled texture builtin '" +
std::string(intrinsic->str()) + "'"); std::string(builtin->str()) + "'");
return false; return false;
} }
if (intrinsic->Signature().IndexOf(sem::ParameterUsage::kOffset) >= 0) { if (builtin->Signature().IndexOf(sem::ParameterUsage::kOffset) >= 0) {
out << "Offset"; out << "Offset";
} }
@ -1299,7 +1299,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
if (auto* depth_ref = arg(Usage::kDepthRef)) { if (auto* depth_ref = arg(Usage::kDepthRef)) {
param_coords = param_coords =
AppendVector(&builder_, param_coords, depth_ref)->Declaration(); AppendVector(&builder_, param_coords, depth_ref)->Declaration();
} else if (intrinsic->Type() == sem::IntrinsicType::kTextureSample) { } else if (builtin->Type() == sem::BuiltinType::kTextureSample) {
// Sampling a depth texture in GLSL always requires a depth reference, so // Sampling a depth texture in GLSL always requires a depth reference, so
// append zero here. // append zero here.
auto* f32 = builder_.create<sem::F32>(); auto* f32 = builder_.create<sem::F32>();
@ -1327,7 +1327,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
} }
// GLSL's textureGather always requires a refZ parameter. // GLSL's textureGather always requires a refZ parameter.
if (is_depth && intrinsic->Type() == sem::IntrinsicType::kTextureGather) { if (is_depth && builtin->Type() == sem::BuiltinType::kTextureGather) {
out << ", 0.0"; out << ", 0.0";
} }
@ -1347,21 +1347,21 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
if (!EmitExpression(out, e)) { if (!EmitExpression(out, e)) {
return false; return false;
} }
} else if (intrinsic->Type() == sem::IntrinsicType::kTextureSample) { } else if (builtin->Type() == sem::BuiltinType::kTextureSample) {
out << ", 0.0f"; out << ", 0.0f";
} }
} }
out << ")"; out << ")";
if (intrinsic->ReturnType()->Is<sem::Void>()) { if (builtin->ReturnType()->Is<sem::Void>()) {
return true; return true;
} }
// If the intrinsic return type does not match the number of elements of the // If the builtin return type does not match the number of elements of the
// GLSL intrinsic, we need to swizzle the expression to generate the correct // GLSL builtin, we need to swizzle the expression to generate the correct
// number of components. // number of components.
uint32_t wgsl_ret_width = 1; uint32_t wgsl_ret_width = 1;
if (auto* vec = intrinsic->ReturnType()->As<sem::Vector>()) { if (auto* vec = builtin->ReturnType()->As<sem::Vector>()) {
wgsl_ret_width = vec->Width(); wgsl_ret_width = vec->Width();
} }
if (wgsl_ret_width < glsl_ret_width) { if (wgsl_ret_width < glsl_ret_width) {
@ -1374,100 +1374,99 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
TINT_ICE(Writer, diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "WGSL return width (" << wgsl_ret_width << "WGSL return width (" << wgsl_ret_width
<< ") is wider than GLSL return width (" << glsl_ret_width << ") for " << ") is wider than GLSL return width (" << glsl_ret_width << ") for "
<< intrinsic->Type(); << builtin->Type();
return false; return false;
} }
return true; return true;
} }
std::string GeneratorImpl::generate_builtin_name( std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
const sem::Intrinsic* intrinsic) { switch (builtin->Type()) {
switch (intrinsic->Type()) { case sem::BuiltinType::kAbs:
case sem::IntrinsicType::kAbs: case sem::BuiltinType::kAcos:
case sem::IntrinsicType::kAcos: case sem::BuiltinType::kAll:
case sem::IntrinsicType::kAll: case sem::BuiltinType::kAny:
case sem::IntrinsicType::kAny: case sem::BuiltinType::kAsin:
case sem::IntrinsicType::kAsin: case sem::BuiltinType::kAtan:
case sem::IntrinsicType::kAtan: case sem::BuiltinType::kCeil:
case sem::IntrinsicType::kCeil: case sem::BuiltinType::kClamp:
case sem::IntrinsicType::kClamp: case sem::BuiltinType::kCos:
case sem::IntrinsicType::kCos: case sem::BuiltinType::kCosh:
case sem::IntrinsicType::kCosh: case sem::BuiltinType::kCross:
case sem::IntrinsicType::kCross: case sem::BuiltinType::kDeterminant:
case sem::IntrinsicType::kDeterminant: case sem::BuiltinType::kDistance:
case sem::IntrinsicType::kDistance: case sem::BuiltinType::kDot:
case sem::IntrinsicType::kDot: case sem::BuiltinType::kExp:
case sem::IntrinsicType::kExp: case sem::BuiltinType::kExp2:
case sem::IntrinsicType::kExp2: case sem::BuiltinType::kFloor:
case sem::IntrinsicType::kFloor: case sem::BuiltinType::kFrexp:
case sem::IntrinsicType::kFrexp: case sem::BuiltinType::kLdexp:
case sem::IntrinsicType::kLdexp: case sem::BuiltinType::kLength:
case sem::IntrinsicType::kLength: case sem::BuiltinType::kLog:
case sem::IntrinsicType::kLog: case sem::BuiltinType::kLog2:
case sem::IntrinsicType::kLog2: case sem::BuiltinType::kMax:
case sem::IntrinsicType::kMax: case sem::BuiltinType::kMin:
case sem::IntrinsicType::kMin: case sem::BuiltinType::kModf:
case sem::IntrinsicType::kModf: case sem::BuiltinType::kNormalize:
case sem::IntrinsicType::kNormalize: case sem::BuiltinType::kPow:
case sem::IntrinsicType::kPow: case sem::BuiltinType::kReflect:
case sem::IntrinsicType::kReflect: case sem::BuiltinType::kRefract:
case sem::IntrinsicType::kRefract: case sem::BuiltinType::kRound:
case sem::IntrinsicType::kRound: case sem::BuiltinType::kSign:
case sem::IntrinsicType::kSign: case sem::BuiltinType::kSin:
case sem::IntrinsicType::kSin: case sem::BuiltinType::kSinh:
case sem::IntrinsicType::kSinh: case sem::BuiltinType::kSqrt:
case sem::IntrinsicType::kSqrt: case sem::BuiltinType::kStep:
case sem::IntrinsicType::kStep: case sem::BuiltinType::kTan:
case sem::IntrinsicType::kTan: case sem::BuiltinType::kTanh:
case sem::IntrinsicType::kTanh: case sem::BuiltinType::kTranspose:
case sem::IntrinsicType::kTranspose: case sem::BuiltinType::kTrunc:
case sem::IntrinsicType::kTrunc: return builtin->str();
return intrinsic->str(); case sem::BuiltinType::kAtan2:
case sem::IntrinsicType::kAtan2:
return "atan"; return "atan";
case sem::IntrinsicType::kCountOneBits: case sem::BuiltinType::kCountOneBits:
return "countbits"; return "countbits";
case sem::IntrinsicType::kDpdx: case sem::BuiltinType::kDpdx:
return "ddx"; return "ddx";
case sem::IntrinsicType::kDpdxCoarse: case sem::BuiltinType::kDpdxCoarse:
return "ddx_coarse"; return "ddx_coarse";
case sem::IntrinsicType::kDpdxFine: case sem::BuiltinType::kDpdxFine:
return "ddx_fine"; return "ddx_fine";
case sem::IntrinsicType::kDpdy: case sem::BuiltinType::kDpdy:
return "ddy"; return "ddy";
case sem::IntrinsicType::kDpdyCoarse: case sem::BuiltinType::kDpdyCoarse:
return "ddy_coarse"; return "ddy_coarse";
case sem::IntrinsicType::kDpdyFine: case sem::BuiltinType::kDpdyFine:
return "ddy_fine"; return "ddy_fine";
case sem::IntrinsicType::kFaceForward: case sem::BuiltinType::kFaceForward:
return "faceforward"; return "faceforward";
case sem::IntrinsicType::kFract: case sem::BuiltinType::kFract:
return "frac"; return "frac";
case sem::IntrinsicType::kFma: case sem::BuiltinType::kFma:
return "mad"; return "mad";
case sem::IntrinsicType::kFwidth: case sem::BuiltinType::kFwidth:
case sem::IntrinsicType::kFwidthCoarse: case sem::BuiltinType::kFwidthCoarse:
case sem::IntrinsicType::kFwidthFine: case sem::BuiltinType::kFwidthFine:
return "fwidth"; return "fwidth";
case sem::IntrinsicType::kInverseSqrt: case sem::BuiltinType::kInverseSqrt:
return "rsqrt"; return "rsqrt";
case sem::IntrinsicType::kIsFinite: case sem::BuiltinType::kIsFinite:
return "isfinite"; return "isfinite";
case sem::IntrinsicType::kIsInf: case sem::BuiltinType::kIsInf:
return "isinf"; return "isinf";
case sem::IntrinsicType::kIsNan: case sem::BuiltinType::kIsNan:
return "isnan"; return "isnan";
case sem::IntrinsicType::kMix: case sem::BuiltinType::kMix:
return "mix"; return "mix";
case sem::IntrinsicType::kReverseBits: case sem::BuiltinType::kReverseBits:
return "reversebits"; return "reversebits";
case sem::IntrinsicType::kSmoothStep: case sem::BuiltinType::kSmoothStep:
return "smoothstep"; return "smoothstep";
default: default:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer, diag::System::Writer,
"Unknown builtin method: " + std::string(intrinsic->str())); "Unknown builtin method: " + std::string(builtin->str()));
} }
return ""; return "";
@ -2624,28 +2623,28 @@ bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
} }
template <typename F> template <typename F>
bool GeneratorImpl::CallIntrinsicHelper(std::ostream& out, bool GeneratorImpl::CallBuiltinHelper(std::ostream& out,
const ast::CallExpression* call, const ast::CallExpression* call,
const sem::Intrinsic* intrinsic, const sem::Builtin* builtin,
F&& build) { F&& build) {
// Generate the helper function if it hasn't been created already // Generate the helper function if it hasn't been created already
auto fn = utils::GetOrCreate(intrinsics_, intrinsic, [&]() -> std::string { auto fn = utils::GetOrCreate(builtins_, builtin, [&]() -> std::string {
TextBuffer b; TextBuffer b;
TINT_DEFER(helpers_.Append(b)); TINT_DEFER(helpers_.Append(b));
auto fn_name = auto fn_name =
UniqueIdentifier(std::string("tint_") + sem::str(intrinsic->Type())); UniqueIdentifier(std::string("tint_") + sem::str(builtin->Type()));
std::vector<std::string> parameter_names; std::vector<std::string> parameter_names;
{ {
auto decl = line(&b); auto decl = line(&b);
if (!EmitTypeAndName(decl, intrinsic->ReturnType(), if (!EmitTypeAndName(decl, builtin->ReturnType(),
ast::StorageClass::kNone, ast::Access::kUndefined, ast::StorageClass::kNone, ast::Access::kUndefined,
fn_name)) { fn_name)) {
return ""; return "";
} }
{ {
ScopedParen sp(decl); ScopedParen sp(decl);
for (auto* param : intrinsic->Parameters()) { for (auto* param : builtin->Parameters()) {
if (!parameter_names.empty()) { if (!parameter_names.empty()) {
decl << ", "; decl << ", ";
} }

View File

@ -42,7 +42,7 @@ namespace tint {
// Forward declarations // Forward declarations
namespace sem { namespace sem {
class Call; class Call;
class Intrinsic; class Builtin;
class TypeConstructor; class TypeConstructor;
class TypeConversion; class TypeConversion;
} // namespace sem } // namespace sem
@ -116,14 +116,14 @@ class GeneratorImpl : public TextGenerator {
bool EmitFunctionCall(std::ostream& out, bool EmitFunctionCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Function* function); const sem::Function* function);
/// Handles generating an intrinsic call expression /// Handles generating a builtin call expression
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
/// @param intrinsic the intrinsic being called /// @param builtin the builtin being called
/// @returns true if the expression is emitted /// @returns true if the expression is emitted
bool EmitIntrinsicCall(std::ostream& out, bool EmitBuiltinCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a type conversion expression /// Handles generating a type conversion expression
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
@ -140,11 +140,11 @@ class GeneratorImpl : public TextGenerator {
bool EmitTypeConstructor(std::ostream& out, bool EmitTypeConstructor(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::TypeConstructor* ctor); const sem::TypeConstructor* ctor);
/// Handles generating a barrier intrinsic call /// Handles generating a barrier builtin call
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param intrinsic the semantic information for the barrier intrinsic /// @param builtin the semantic information for the barrier builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitBarrierCall(std::ostream& out, const sem::Intrinsic* intrinsic); bool EmitBarrierCall(std::ostream& out, const sem::Builtin* builtin);
/// Handles generating an atomic intrinsic call for a storage buffer variable /// Handles generating an atomic intrinsic call for a storage buffer variable
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
@ -154,92 +154,92 @@ class GeneratorImpl : public TextGenerator {
std::ostream& out, std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const transform::DecomposeMemoryAccess::Intrinsic* intrinsic); const transform::DecomposeMemoryAccess::Intrinsic* intrinsic);
/// Handles generating an atomic intrinsic call for a workgroup variable /// Handles generating an atomic builtin call for a workgroup variable
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the atomic intrinsic /// @param builtin the semantic information for the atomic builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitWorkgroupAtomicCall(std::ostream& out, bool EmitWorkgroupAtomicCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to a texture function (`textureSample`, /// Handles generating a call to a texture function (`textureSample`,
/// `textureSampleGrad`, etc) /// `textureSampleGrad`, etc)
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
/// @param intrinsic the semantic information for the texture intrinsic /// @param builtin the semantic information for the texture builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitTextureCall(std::ostream& out, bool EmitTextureCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `select()` intrinsic /// Handles generating a call to the `select()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitSelectCall(std::ostream& out, const ast::CallExpression* expr); bool EmitSelectCall(std::ostream& out, const ast::CallExpression* expr);
/// Handles generating a call to the `dot()` intrinsic /// Handles generating a call to the `dot()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitDotCall(std::ostream& out, bool EmitDotCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `modf()` intrinsic /// Handles generating a call to the `modf()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitModfCall(std::ostream& out, bool EmitModfCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `frexp()` intrinsic /// Handles generating a call to the `frexp()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitFrexpCall(std::ostream& out, bool EmitFrexpCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `isNormal()` intrinsic /// Handles generating a call to the `isNormal()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitIsNormalCall(std::ostream& out, bool EmitIsNormalCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `degrees()` intrinsic /// Handles generating a call to the `degrees()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitDegreesCall(std::ostream& out, bool EmitDegreesCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `radians()` intrinsic /// Handles generating a call to the `radians()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitRadiansCall(std::ostream& out, bool EmitRadiansCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to data packing intrinsic /// Handles generating a call to data packing builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the texture intrinsic /// @param builtin the semantic information for the texture builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitDataPackingCall(std::ostream& out, bool EmitDataPackingCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to data unpacking intrinsic /// Handles generating a call to data unpacking builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the texture intrinsic /// @param builtin the semantic information for the texture builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitDataUnpackingCall(std::ostream& out, bool EmitDataUnpackingCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles a case statement /// Handles a case statement
/// @param stmt the statement /// @param stmt the statement
/// @returns true if the statement was emitted successfully /// @returns true if the statement was emitted successfully
@ -407,9 +407,9 @@ class GeneratorImpl : public TextGenerator {
/// @returns true if the variable was emitted /// @returns true if the variable was emitted
bool EmitProgramConstVariable(const ast::Variable* var); bool EmitProgramConstVariable(const ast::Variable* var);
/// Handles generating a builtin method name /// Handles generating a builtin method name
/// @param intrinsic the semantic info for the intrinsic /// @param builtin the semantic info for the builtin
/// @returns the name or "" if not valid /// @returns the name or "" if not valid
std::string generate_builtin_name(const sem::Intrinsic* intrinsic); std::string generate_builtin_name(const sem::Builtin* builtin);
/// Converts a builtin to a gl_ string /// Converts a builtin to a gl_ string
/// @param builtin the builtin to convert /// @param builtin the builtin to convert
/// @param stage pipeline stage in which this builtin is used /// @param stage pipeline stage in which this builtin is used
@ -444,13 +444,13 @@ class GeneratorImpl : public TextGenerator {
}; };
}; };
/// CallIntrinsicHelper will call the intrinsic helper function, creating it /// CallBuiltinHelper will call the builtin helper function, creating it
/// if it hasn't been built already. If the intrinsic needs to be built then /// if it hasn't been built already. If the builtin needs to be built then
/// CallIntrinsicHelper will generate the function signature and will call /// CallBuiltinHelper will generate the function signature and will call
/// `build` to emit the body of the function. /// `build` to emit the body of the function.
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @param build a function with the signature: /// @param build a function with the signature:
/// `bool(TextBuffer* buffer, const std::vector<std::string>& params)` /// `bool(TextBuffer* buffer, const std::vector<std::string>& params)`
/// Where: /// Where:
@ -458,16 +458,16 @@ class GeneratorImpl : public TextGenerator {
/// `params` is the name of all the generated function parameters /// `params` is the name of all the generated function parameters
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
template <typename F> template <typename F>
bool CallIntrinsicHelper(std::ostream& out, bool CallBuiltinHelper(std::ostream& out,
const ast::CallExpression* call, const ast::CallExpression* call,
const sem::Intrinsic* intrinsic, const sem::Builtin* builtin,
F&& build); F&& build);
TextBuffer helpers_; // Helper functions emitted at the top of the output TextBuffer helpers_; // Helper functions emitted at the top of the output
std::function<bool()> emit_continuing_; std::function<bool()> emit_continuing_;
std::unordered_map<DMAIntrinsic, std::string, DMAIntrinsic::Hasher> std::unordered_map<DMAIntrinsic, std::string, DMAIntrinsic::Hasher>
dma_intrinsics_; dma_intrinsics_;
std::unordered_map<const sem::Intrinsic*, std::string> intrinsics_; std::unordered_map<const sem::Builtin*, std::string> builtins_;
std::unordered_map<const sem::Struct*, std::string> structure_builders_; std::unordered_map<const sem::Struct*, std::string> structure_builders_;
std::unordered_map<const sem::Vector*, std::string> dynamic_vector_write_; std::unordered_map<const sem::Vector*, std::string> dynamic_vector_write_;
std::unordered_map<const sem::Vector*, std::string> int_dot_funcs_; std::unordered_map<const sem::Vector*, std::string> int_dot_funcs_;

View File

@ -23,11 +23,11 @@ namespace writer {
namespace glsl { namespace glsl {
namespace { namespace {
using IntrinsicType = sem::IntrinsicType; using BuiltinType = sem::BuiltinType;
using ::testing::HasSubstr; using ::testing::HasSubstr;
using GlslGeneratorImplTest_Intrinsic = TestHelper; using GlslGeneratorImplTest_Builtin = TestHelper;
enum class ParamType { enum class ParamType {
kF32, kF32,
@ -35,12 +35,12 @@ enum class ParamType {
kBool, kBool,
}; };
struct IntrinsicData { struct BuiltinData {
IntrinsicType intrinsic; BuiltinType builtin;
ParamType type; ParamType type;
const char* glsl_name; const char* glsl_name;
}; };
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) { inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
out << data.glsl_name; out << data.glsl_name;
switch (data.type) { switch (data.type) {
case ParamType::kF32: case ParamType::kF32:
@ -57,104 +57,104 @@ inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
return out; return out;
} }
const ast::CallExpression* GenerateCall(IntrinsicType intrinsic, const ast::CallExpression* GenerateCall(BuiltinType builtin,
ParamType type, ParamType type,
ProgramBuilder* builder) { ProgramBuilder* builder) {
std::string name; std::string name;
std::ostringstream str(name); std::ostringstream str(name);
str << intrinsic; str << builtin;
switch (intrinsic) { switch (builtin) {
case IntrinsicType::kAcos: case BuiltinType::kAcos:
case IntrinsicType::kAsin: case BuiltinType::kAsin:
case IntrinsicType::kAtan: case BuiltinType::kAtan:
case IntrinsicType::kCeil: case BuiltinType::kCeil:
case IntrinsicType::kCos: case BuiltinType::kCos:
case IntrinsicType::kCosh: case BuiltinType::kCosh:
case IntrinsicType::kDpdx: case BuiltinType::kDpdx:
case IntrinsicType::kDpdxCoarse: case BuiltinType::kDpdxCoarse:
case IntrinsicType::kDpdxFine: case BuiltinType::kDpdxFine:
case IntrinsicType::kDpdy: case BuiltinType::kDpdy:
case IntrinsicType::kDpdyCoarse: case BuiltinType::kDpdyCoarse:
case IntrinsicType::kDpdyFine: case BuiltinType::kDpdyFine:
case IntrinsicType::kExp: case BuiltinType::kExp:
case IntrinsicType::kExp2: case BuiltinType::kExp2:
case IntrinsicType::kFloor: case BuiltinType::kFloor:
case IntrinsicType::kFract: case BuiltinType::kFract:
case IntrinsicType::kFwidth: case BuiltinType::kFwidth:
case IntrinsicType::kFwidthCoarse: case BuiltinType::kFwidthCoarse:
case IntrinsicType::kFwidthFine: case BuiltinType::kFwidthFine:
case IntrinsicType::kInverseSqrt: case BuiltinType::kInverseSqrt:
case IntrinsicType::kIsFinite: case BuiltinType::kIsFinite:
case IntrinsicType::kIsInf: case BuiltinType::kIsInf:
case IntrinsicType::kIsNan: case BuiltinType::kIsNan:
case IntrinsicType::kIsNormal: case BuiltinType::kIsNormal:
case IntrinsicType::kLength: case BuiltinType::kLength:
case IntrinsicType::kLog: case BuiltinType::kLog:
case IntrinsicType::kLog2: case BuiltinType::kLog2:
case IntrinsicType::kNormalize: case BuiltinType::kNormalize:
case IntrinsicType::kRound: case BuiltinType::kRound:
case IntrinsicType::kSin: case BuiltinType::kSin:
case IntrinsicType::kSinh: case BuiltinType::kSinh:
case IntrinsicType::kSqrt: case BuiltinType::kSqrt:
case IntrinsicType::kTan: case BuiltinType::kTan:
case IntrinsicType::kTanh: case BuiltinType::kTanh:
case IntrinsicType::kTrunc: case BuiltinType::kTrunc:
case IntrinsicType::kSign: case BuiltinType::kSign:
return builder->Call(str.str(), "f2"); return builder->Call(str.str(), "f2");
case IntrinsicType::kLdexp: case BuiltinType::kLdexp:
return builder->Call(str.str(), "f2", "i2"); return builder->Call(str.str(), "f2", "i2");
case IntrinsicType::kAtan2: case BuiltinType::kAtan2:
case IntrinsicType::kDot: case BuiltinType::kDot:
case IntrinsicType::kDistance: case BuiltinType::kDistance:
case IntrinsicType::kPow: case BuiltinType::kPow:
case IntrinsicType::kReflect: case BuiltinType::kReflect:
case IntrinsicType::kStep: case BuiltinType::kStep:
return builder->Call(str.str(), "f2", "f2"); return builder->Call(str.str(), "f2", "f2");
case IntrinsicType::kCross: case BuiltinType::kCross:
return builder->Call(str.str(), "f3", "f3"); return builder->Call(str.str(), "f3", "f3");
case IntrinsicType::kFma: case BuiltinType::kFma:
case IntrinsicType::kMix: case BuiltinType::kMix:
case IntrinsicType::kFaceForward: case BuiltinType::kFaceForward:
case IntrinsicType::kSmoothStep: case BuiltinType::kSmoothStep:
return builder->Call(str.str(), "f2", "f2", "f2"); return builder->Call(str.str(), "f2", "f2", "f2");
case IntrinsicType::kAll: case BuiltinType::kAll:
case IntrinsicType::kAny: case BuiltinType::kAny:
return builder->Call(str.str(), "b2"); return builder->Call(str.str(), "b2");
case IntrinsicType::kAbs: case BuiltinType::kAbs:
if (type == ParamType::kF32) { if (type == ParamType::kF32) {
return builder->Call(str.str(), "f2"); return builder->Call(str.str(), "f2");
} else { } else {
return builder->Call(str.str(), "u2"); return builder->Call(str.str(), "u2");
} }
case IntrinsicType::kCountOneBits: case BuiltinType::kCountOneBits:
case IntrinsicType::kReverseBits: case BuiltinType::kReverseBits:
return builder->Call(str.str(), "u2"); return builder->Call(str.str(), "u2");
case IntrinsicType::kMax: case BuiltinType::kMax:
case IntrinsicType::kMin: case BuiltinType::kMin:
if (type == ParamType::kF32) { if (type == ParamType::kF32) {
return builder->Call(str.str(), "f2", "f2"); return builder->Call(str.str(), "f2", "f2");
} else { } else {
return builder->Call(str.str(), "u2", "u2"); return builder->Call(str.str(), "u2", "u2");
} }
case IntrinsicType::kClamp: case BuiltinType::kClamp:
if (type == ParamType::kF32) { if (type == ParamType::kF32) {
return builder->Call(str.str(), "f2", "f2", "f2"); return builder->Call(str.str(), "f2", "f2", "f2");
} else { } else {
return builder->Call(str.str(), "u2", "u2", "u2"); return builder->Call(str.str(), "u2", "u2", "u2");
} }
case IntrinsicType::kSelect: case BuiltinType::kSelect:
return builder->Call(str.str(), "f2", "f2", "b2"); return builder->Call(str.str(), "f2", "f2", "b2");
case IntrinsicType::kDeterminant: case BuiltinType::kDeterminant:
return builder->Call(str.str(), "m2x2"); return builder->Call(str.str(), "m2x2");
case IntrinsicType::kTranspose: case BuiltinType::kTranspose:
return builder->Call(str.str(), "m3x2"); return builder->Call(str.str(), "m3x2");
default: default:
break; break;
} }
return nullptr; return nullptr;
} }
using GlslIntrinsicTest = TestParamHelper<IntrinsicData>; using GlslBuiltinTest = TestParamHelper<BuiltinData>;
TEST_P(GlslIntrinsicTest, Emit) { TEST_P(GlslBuiltinTest, Emit) {
auto param = GetParam(); auto param = GetParam();
Global("f2", ty.vec2<f32>(), ast::StorageClass::kPrivate); Global("f2", ty.vec2<f32>(), ast::StorageClass::kPrivate);
@ -165,8 +165,8 @@ TEST_P(GlslIntrinsicTest, Emit) {
Global("m2x2", ty.mat2x2<f32>(), ast::StorageClass::kPrivate); Global("m2x2", ty.mat2x2<f32>(), ast::StorageClass::kPrivate);
Global("m3x2", ty.mat3x2<f32>(), ast::StorageClass::kPrivate); Global("m3x2", ty.mat3x2<f32>(), ast::StorageClass::kPrivate);
auto* call = GenerateCall(param.intrinsic, param.type, this); auto* call = GenerateCall(param.builtin, param.type, this);
ASSERT_NE(nullptr, call) << "Unhandled intrinsic"; ASSERT_NE(nullptr, call) << "Unhandled builtin";
Func("func", {}, ty.void_(), {CallStmt(call)}, Func("func", {}, ty.void_(), {CallStmt(call)},
{create<ast::StageAttribute>(ast::PipelineStage::kFragment)}); {create<ast::StageAttribute>(ast::PipelineStage::kFragment)});
@ -176,89 +176,82 @@ TEST_P(GlslIntrinsicTest, Emit) {
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* target = sem->Target(); auto* target = sem->Target();
ASSERT_NE(target, nullptr); ASSERT_NE(target, nullptr);
auto* intrinsic = target->As<sem::Intrinsic>(); auto* builtin = target->As<sem::Builtin>();
ASSERT_NE(intrinsic, nullptr); ASSERT_NE(builtin, nullptr);
EXPECT_EQ(gen.generate_builtin_name(intrinsic), param.glsl_name); EXPECT_EQ(gen.generate_builtin_name(builtin), param.glsl_name);
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
GlslGeneratorImplTest_Intrinsic, GlslGeneratorImplTest_Builtin,
GlslIntrinsicTest, GlslBuiltinTest,
testing::Values( testing::Values(
IntrinsicData{IntrinsicType::kAbs, ParamType::kF32, "abs"}, BuiltinData{BuiltinType::kAbs, ParamType::kF32, "abs"},
IntrinsicData{IntrinsicType::kAbs, ParamType::kU32, "abs"}, BuiltinData{BuiltinType::kAbs, ParamType::kU32, "abs"},
IntrinsicData{IntrinsicType::kAcos, ParamType::kF32, "acos"}, BuiltinData{BuiltinType::kAcos, ParamType::kF32, "acos"},
IntrinsicData{IntrinsicType::kAll, ParamType::kBool, "all"}, BuiltinData{BuiltinType::kAll, ParamType::kBool, "all"},
IntrinsicData{IntrinsicType::kAny, ParamType::kBool, "any"}, BuiltinData{BuiltinType::kAny, ParamType::kBool, "any"},
IntrinsicData{IntrinsicType::kAsin, ParamType::kF32, "asin"}, BuiltinData{BuiltinType::kAsin, ParamType::kF32, "asin"},
IntrinsicData{IntrinsicType::kAtan, ParamType::kF32, "atan"}, BuiltinData{BuiltinType::kAtan, ParamType::kF32, "atan"},
IntrinsicData{IntrinsicType::kAtan2, ParamType::kF32, "atan"}, BuiltinData{BuiltinType::kAtan2, ParamType::kF32, "atan"},
IntrinsicData{IntrinsicType::kCeil, ParamType::kF32, "ceil"}, BuiltinData{BuiltinType::kCeil, ParamType::kF32, "ceil"},
IntrinsicData{IntrinsicType::kClamp, ParamType::kF32, "clamp"}, BuiltinData{BuiltinType::kClamp, ParamType::kF32, "clamp"},
IntrinsicData{IntrinsicType::kClamp, ParamType::kU32, "clamp"}, BuiltinData{BuiltinType::kClamp, ParamType::kU32, "clamp"},
IntrinsicData{IntrinsicType::kCos, ParamType::kF32, "cos"}, BuiltinData{BuiltinType::kCos, ParamType::kF32, "cos"},
IntrinsicData{IntrinsicType::kCosh, ParamType::kF32, "cosh"}, BuiltinData{BuiltinType::kCosh, ParamType::kF32, "cosh"},
IntrinsicData{IntrinsicType::kCountOneBits, ParamType::kU32, BuiltinData{BuiltinType::kCountOneBits, ParamType::kU32, "countbits"},
"countbits"}, BuiltinData{BuiltinType::kCross, ParamType::kF32, "cross"},
IntrinsicData{IntrinsicType::kCross, ParamType::kF32, "cross"}, BuiltinData{BuiltinType::kDeterminant, ParamType::kF32, "determinant"},
IntrinsicData{IntrinsicType::kDeterminant, ParamType::kF32, BuiltinData{BuiltinType::kDistance, ParamType::kF32, "distance"},
"determinant"}, BuiltinData{BuiltinType::kDot, ParamType::kF32, "dot"},
IntrinsicData{IntrinsicType::kDistance, ParamType::kF32, "distance"}, BuiltinData{BuiltinType::kDpdx, ParamType::kF32, "ddx"},
IntrinsicData{IntrinsicType::kDot, ParamType::kF32, "dot"}, BuiltinData{BuiltinType::kDpdxCoarse, ParamType::kF32, "ddx_coarse"},
IntrinsicData{IntrinsicType::kDpdx, ParamType::kF32, "ddx"}, BuiltinData{BuiltinType::kDpdxFine, ParamType::kF32, "ddx_fine"},
IntrinsicData{IntrinsicType::kDpdxCoarse, ParamType::kF32, BuiltinData{BuiltinType::kDpdy, ParamType::kF32, "ddy"},
"ddx_coarse"}, BuiltinData{BuiltinType::kDpdyCoarse, ParamType::kF32, "ddy_coarse"},
IntrinsicData{IntrinsicType::kDpdxFine, ParamType::kF32, "ddx_fine"}, BuiltinData{BuiltinType::kDpdyFine, ParamType::kF32, "ddy_fine"},
IntrinsicData{IntrinsicType::kDpdy, ParamType::kF32, "ddy"}, BuiltinData{BuiltinType::kExp, ParamType::kF32, "exp"},
IntrinsicData{IntrinsicType::kDpdyCoarse, ParamType::kF32, BuiltinData{BuiltinType::kExp2, ParamType::kF32, "exp2"},
"ddy_coarse"}, BuiltinData{BuiltinType::kFaceForward, ParamType::kF32, "faceforward"},
IntrinsicData{IntrinsicType::kDpdyFine, ParamType::kF32, "ddy_fine"}, BuiltinData{BuiltinType::kFloor, ParamType::kF32, "floor"},
IntrinsicData{IntrinsicType::kExp, ParamType::kF32, "exp"}, BuiltinData{BuiltinType::kFma, ParamType::kF32, "mad"},
IntrinsicData{IntrinsicType::kExp2, ParamType::kF32, "exp2"}, BuiltinData{BuiltinType::kFract, ParamType::kF32, "frac"},
IntrinsicData{IntrinsicType::kFaceForward, ParamType::kF32, BuiltinData{BuiltinType::kFwidth, ParamType::kF32, "fwidth"},
"faceforward"}, BuiltinData{BuiltinType::kFwidthCoarse, ParamType::kF32, "fwidth"},
IntrinsicData{IntrinsicType::kFloor, ParamType::kF32, "floor"}, BuiltinData{BuiltinType::kFwidthFine, ParamType::kF32, "fwidth"},
IntrinsicData{IntrinsicType::kFma, ParamType::kF32, "mad"}, BuiltinData{BuiltinType::kInverseSqrt, ParamType::kF32, "rsqrt"},
IntrinsicData{IntrinsicType::kFract, ParamType::kF32, "frac"}, BuiltinData{BuiltinType::kIsFinite, ParamType::kF32, "isfinite"},
IntrinsicData{IntrinsicType::kFwidth, ParamType::kF32, "fwidth"}, BuiltinData{BuiltinType::kIsInf, ParamType::kF32, "isinf"},
IntrinsicData{IntrinsicType::kFwidthCoarse, ParamType::kF32, "fwidth"}, BuiltinData{BuiltinType::kIsNan, ParamType::kF32, "isnan"},
IntrinsicData{IntrinsicType::kFwidthFine, ParamType::kF32, "fwidth"}, BuiltinData{BuiltinType::kLdexp, ParamType::kF32, "ldexp"},
IntrinsicData{IntrinsicType::kInverseSqrt, ParamType::kF32, "rsqrt"}, BuiltinData{BuiltinType::kLength, ParamType::kF32, "length"},
IntrinsicData{IntrinsicType::kIsFinite, ParamType::kF32, "isfinite"}, BuiltinData{BuiltinType::kLog, ParamType::kF32, "log"},
IntrinsicData{IntrinsicType::kIsInf, ParamType::kF32, "isinf"}, BuiltinData{BuiltinType::kLog2, ParamType::kF32, "log2"},
IntrinsicData{IntrinsicType::kIsNan, ParamType::kF32, "isnan"}, BuiltinData{BuiltinType::kMax, ParamType::kF32, "max"},
IntrinsicData{IntrinsicType::kLdexp, ParamType::kF32, "ldexp"}, BuiltinData{BuiltinType::kMax, ParamType::kU32, "max"},
IntrinsicData{IntrinsicType::kLength, ParamType::kF32, "length"}, BuiltinData{BuiltinType::kMin, ParamType::kF32, "min"},
IntrinsicData{IntrinsicType::kLog, ParamType::kF32, "log"}, BuiltinData{BuiltinType::kMin, ParamType::kU32, "min"},
IntrinsicData{IntrinsicType::kLog2, ParamType::kF32, "log2"}, BuiltinData{BuiltinType::kMix, ParamType::kF32, "mix"},
IntrinsicData{IntrinsicType::kMax, ParamType::kF32, "max"}, BuiltinData{BuiltinType::kNormalize, ParamType::kF32, "normalize"},
IntrinsicData{IntrinsicType::kMax, ParamType::kU32, "max"}, BuiltinData{BuiltinType::kPow, ParamType::kF32, "pow"},
IntrinsicData{IntrinsicType::kMin, ParamType::kF32, "min"}, BuiltinData{BuiltinType::kReflect, ParamType::kF32, "reflect"},
IntrinsicData{IntrinsicType::kMin, ParamType::kU32, "min"}, BuiltinData{BuiltinType::kReverseBits, ParamType::kU32, "reversebits"},
IntrinsicData{IntrinsicType::kMix, ParamType::kF32, "mix"}, BuiltinData{BuiltinType::kRound, ParamType::kU32, "round"},
IntrinsicData{IntrinsicType::kNormalize, ParamType::kF32, "normalize"}, BuiltinData{BuiltinType::kSign, ParamType::kF32, "sign"},
IntrinsicData{IntrinsicType::kPow, ParamType::kF32, "pow"}, BuiltinData{BuiltinType::kSin, ParamType::kF32, "sin"},
IntrinsicData{IntrinsicType::kReflect, ParamType::kF32, "reflect"}, BuiltinData{BuiltinType::kSinh, ParamType::kF32, "sinh"},
IntrinsicData{IntrinsicType::kReverseBits, ParamType::kU32, BuiltinData{BuiltinType::kSmoothStep, ParamType::kF32, "smoothstep"},
"reversebits"}, BuiltinData{BuiltinType::kSqrt, ParamType::kF32, "sqrt"},
IntrinsicData{IntrinsicType::kRound, ParamType::kU32, "round"}, BuiltinData{BuiltinType::kStep, ParamType::kF32, "step"},
IntrinsicData{IntrinsicType::kSign, ParamType::kF32, "sign"}, BuiltinData{BuiltinType::kTan, ParamType::kF32, "tan"},
IntrinsicData{IntrinsicType::kSin, ParamType::kF32, "sin"}, BuiltinData{BuiltinType::kTanh, ParamType::kF32, "tanh"},
IntrinsicData{IntrinsicType::kSinh, ParamType::kF32, "sinh"}, BuiltinData{BuiltinType::kTranspose, ParamType::kF32, "transpose"},
IntrinsicData{IntrinsicType::kSmoothStep, ParamType::kF32, BuiltinData{BuiltinType::kTrunc, ParamType::kF32, "trunc"}));
"smoothstep"},
IntrinsicData{IntrinsicType::kSqrt, ParamType::kF32, "sqrt"},
IntrinsicData{IntrinsicType::kStep, ParamType::kF32, "step"},
IntrinsicData{IntrinsicType::kTan, ParamType::kF32, "tan"},
IntrinsicData{IntrinsicType::kTanh, ParamType::kF32, "tanh"},
IntrinsicData{IntrinsicType::kTranspose, ParamType::kF32, "transpose"},
IntrinsicData{IntrinsicType::kTrunc, ParamType::kF32, "trunc"}));
TEST_F(GlslGeneratorImplTest_Intrinsic, DISABLED_Intrinsic_IsNormal) { TEST_F(GlslGeneratorImplTest_Builtin, DISABLED_Builtin_IsNormal) {
FAIL(); FAIL();
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Intrinsic_Call) { TEST_F(GlslGeneratorImplTest_Builtin, Builtin_Call) {
auto* call = Call("dot", "param1", "param2"); auto* call = Call("dot", "param1", "param2");
Global("param1", ty.vec3<f32>(), ast::StorageClass::kPrivate); Global("param1", ty.vec3<f32>(), ast::StorageClass::kPrivate);
@ -274,7 +267,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Intrinsic_Call) {
EXPECT_EQ(out.str(), "dot(param1, param2)"); EXPECT_EQ(out.str(), "dot(param1, param2)");
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Select_Scalar) { TEST_F(GlslGeneratorImplTest_Builtin, Select_Scalar) {
auto* call = Call("select", 1.0f, 2.0f, true); auto* call = Call("select", 1.0f, 2.0f, true);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -285,7 +278,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Select_Scalar) {
EXPECT_EQ(out.str(), "(true ? 2.0f : 1.0f)"); EXPECT_EQ(out.str(), "(true ? 2.0f : 1.0f)");
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Select_Vector) { TEST_F(GlslGeneratorImplTest_Builtin, Select_Vector) {
auto* call = auto* call =
Call("select", vec2<i32>(1, 2), vec2<i32>(3, 4), vec2<bool>(true, false)); Call("select", vec2<i32>(1, 2), vec2<i32>(3, 4), vec2<bool>(true, false));
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -298,7 +291,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Select_Vector) {
} }
#if 0 #if 0
TEST_F(GlslGeneratorImplTest_Intrinsic, Modf_Scalar) { TEST_F(GlslGeneratorImplTest_Builtin, Modf_Scalar) {
auto* res = Var("res", ty.f32()); auto* res = Var("res", ty.f32());
auto* call = Call("modf", 1.0f, AddressOf(res)); auto* call = Call("modf", 1.0f, AddressOf(res));
WrapInFunction(res, call); WrapInFunction(res, call);
@ -309,7 +302,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Modf_Scalar) {
EXPECT_THAT(gen.result(), HasSubstr("modf(1.0f, res)")); EXPECT_THAT(gen.result(), HasSubstr("modf(1.0f, res)"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Modf_Vector) { TEST_F(GlslGeneratorImplTest_Builtin, Modf_Vector) {
auto* res = Var("res", ty.vec3<f32>()); auto* res = Var("res", ty.vec3<f32>());
auto* call = Call("modf", vec3<f32>(), AddressOf(res)); auto* call = Call("modf", vec3<f32>(), AddressOf(res));
WrapInFunction(res, call); WrapInFunction(res, call);
@ -320,7 +313,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Modf_Vector) {
EXPECT_THAT(gen.result(), HasSubstr("modf(vec3(0.0f, 0.0f, 0.0f), res)")); EXPECT_THAT(gen.result(), HasSubstr("modf(vec3(0.0f, 0.0f, 0.0f), res)"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Frexp_Scalar_i32) { TEST_F(GlslGeneratorImplTest_Builtin, Frexp_Scalar_i32) {
auto* exp = Var("exp", ty.i32()); auto* exp = Var("exp", ty.i32());
auto* call = Call("frexp", 1.0f, AddressOf(exp)); auto* call = Call("frexp", 1.0f, AddressOf(exp));
WrapInFunction(exp, call); WrapInFunction(exp, call);
@ -336,7 +329,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Frexp_Scalar_i32) {
)")); )"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Frexp_Vector_i32) { TEST_F(GlslGeneratorImplTest_Builtin, Frexp_Vector_i32) {
auto* res = Var("res", ty.vec3<i32>()); auto* res = Var("res", ty.vec3<i32>());
auto* call = Call("frexp", vec3<f32>(), AddressOf(res)); auto* call = Call("frexp", vec3<f32>(), AddressOf(res));
WrapInFunction(res, call); WrapInFunction(res, call);
@ -352,7 +345,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Frexp_Vector_i32) {
)")); )"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, IsNormal_Scalar) { TEST_F(GlslGeneratorImplTest_Builtin, IsNormal_Scalar) {
auto* val = Var("val", ty.f32()); auto* val = Var("val", ty.f32());
auto* call = Call("isNormal", val); auto* call = Call("isNormal", val);
WrapInFunction(val, call); WrapInFunction(val, call);
@ -367,7 +360,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, IsNormal_Scalar) {
)")); )"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, IsNormal_Vector) { TEST_F(GlslGeneratorImplTest_Builtin, IsNormal_Vector) {
auto* val = Var("val", ty.vec3<f32>()); auto* val = Var("val", ty.vec3<f32>());
auto* call = Call("isNormal", val); auto* call = Call("isNormal", val);
WrapInFunction(val, call); WrapInFunction(val, call);
@ -383,7 +376,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, IsNormal_Vector) {
} }
#endif #endif
TEST_F(GlslGeneratorImplTest_Intrinsic, Degrees_Scalar) { TEST_F(GlslGeneratorImplTest_Builtin, Degrees_Scalar) {
auto* val = Var("val", ty.f32()); auto* val = Var("val", ty.f32());
auto* call = Call("degrees", val); auto* call = Call("degrees", val);
WrapInFunction(val, call); WrapInFunction(val, call);
@ -412,7 +405,7 @@ void main() {
)"); )");
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Degrees_Vector) { TEST_F(GlslGeneratorImplTest_Builtin, Degrees_Vector) {
auto* val = Var("val", ty.vec3<f32>()); auto* val = Var("val", ty.vec3<f32>());
auto* call = Call("degrees", val); auto* call = Call("degrees", val);
WrapInFunction(val, call); WrapInFunction(val, call);
@ -441,7 +434,7 @@ void main() {
)"); )");
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Radians_Scalar) { TEST_F(GlslGeneratorImplTest_Builtin, Radians_Scalar) {
auto* val = Var("val", ty.f32()); auto* val = Var("val", ty.f32());
auto* call = Call("radians", val); auto* call = Call("radians", val);
WrapInFunction(val, call); WrapInFunction(val, call);
@ -470,7 +463,7 @@ void main() {
)"); )");
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Radians_Vector) { TEST_F(GlslGeneratorImplTest_Builtin, Radians_Vector) {
auto* val = Var("val", ty.vec3<f32>()); auto* val = Var("val", ty.vec3<f32>());
auto* call = Call("radians", val); auto* call = Call("radians", val);
WrapInFunction(val, call); WrapInFunction(val, call);
@ -500,7 +493,7 @@ void main() {
} }
#if 0 #if 0
TEST_F(GlslGeneratorImplTest_Intrinsic, Pack4x8Snorm) { TEST_F(GlslGeneratorImplTest_Builtin, Pack4x8Snorm) {
auto* call = Call("pack4x8snorm", "p1"); auto* call = Call("pack4x8snorm", "p1");
Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate); Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -515,7 +508,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Pack4x8Snorm) {
"tint_tmp.z << 16 | tint_tmp.w << 24)")); "tint_tmp.z << 16 | tint_tmp.w << 24)"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Pack4x8Unorm) { TEST_F(GlslGeneratorImplTest_Builtin, Pack4x8Unorm) {
auto* call = Call("pack4x8unorm", "p1"); auto* call = Call("pack4x8unorm", "p1");
Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate); Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -530,7 +523,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Pack4x8Unorm) {
"tint_tmp.z << 16 | tint_tmp.w << 24)")); "tint_tmp.z << 16 | tint_tmp.w << 24)"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Pack2x16Snorm) { TEST_F(GlslGeneratorImplTest_Builtin, Pack2x16Snorm) {
auto* call = Call("pack2x16snorm", "p1"); auto* call = Call("pack2x16snorm", "p1");
Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate); Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -544,7 +537,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Pack2x16Snorm) {
EXPECT_THAT(out.str(), HasSubstr("asuint(tint_tmp.x | tint_tmp.y << 16)")); EXPECT_THAT(out.str(), HasSubstr("asuint(tint_tmp.x | tint_tmp.y << 16)"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Pack2x16Unorm) { TEST_F(GlslGeneratorImplTest_Builtin, Pack2x16Unorm) {
auto* call = Call("pack2x16unorm", "p1"); auto* call = Call("pack2x16unorm", "p1");
Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate); Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -558,7 +551,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Pack2x16Unorm) {
EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)")); EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Pack2x16Float) { TEST_F(GlslGeneratorImplTest_Builtin, Pack2x16Float) {
auto* call = Call("pack2x16float", "p1"); auto* call = Call("pack2x16float", "p1");
Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate); Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -571,7 +564,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Pack2x16Float) {
EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)")); EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack4x8Snorm) { TEST_F(GlslGeneratorImplTest_Builtin, Unpack4x8Snorm) {
auto* call = Call("unpack4x8snorm", "p1"); auto* call = Call("unpack4x8snorm", "p1");
Global("p1", ty.u32(), ast::StorageClass::kPrivate); Global("p1", ty.u32(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -588,7 +581,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack4x8Snorm) {
HasSubstr("clamp(float4(tint_tmp) / 127.0, -1.0, 1.0)")); HasSubstr("clamp(float4(tint_tmp) / 127.0, -1.0, 1.0)"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack4x8Unorm) { TEST_F(GlslGeneratorImplTest_Builtin, Unpack4x8Unorm) {
auto* call = Call("unpack4x8unorm", "p1"); auto* call = Call("unpack4x8unorm", "p1");
Global("p1", ty.u32(), ast::StorageClass::kPrivate); Global("p1", ty.u32(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -605,7 +598,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack4x8Unorm) {
EXPECT_THAT(out.str(), HasSubstr("float4(tint_tmp) / 255.0")); EXPECT_THAT(out.str(), HasSubstr("float4(tint_tmp) / 255.0"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack2x16Snorm) { TEST_F(GlslGeneratorImplTest_Builtin, Unpack2x16Snorm) {
auto* call = Call("unpack2x16snorm", "p1"); auto* call = Call("unpack2x16snorm", "p1");
Global("p1", ty.u32(), ast::StorageClass::kPrivate); Global("p1", ty.u32(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -622,7 +615,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack2x16Snorm) {
HasSubstr("clamp(float2(tint_tmp) / 32767.0, -1.0, 1.0)")); HasSubstr("clamp(float2(tint_tmp) / 32767.0, -1.0, 1.0)"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack2x16Unorm) { TEST_F(GlslGeneratorImplTest_Builtin, Unpack2x16Unorm) {
auto* call = Call("unpack2x16unorm", "p1"); auto* call = Call("unpack2x16unorm", "p1");
Global("p1", ty.u32(), ast::StorageClass::kPrivate); Global("p1", ty.u32(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -638,7 +631,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack2x16Unorm) {
EXPECT_THAT(out.str(), HasSubstr("float2(tint_tmp) / 65535.0")); EXPECT_THAT(out.str(), HasSubstr("float2(tint_tmp) / 65535.0"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack2x16Float) { TEST_F(GlslGeneratorImplTest_Builtin, Unpack2x16Float) {
auto* call = Call("unpack2x16float", "p1"); auto* call = Call("unpack2x16float", "p1");
Global("p1", ty.u32(), ast::StorageClass::kPrivate); Global("p1", ty.u32(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -652,7 +645,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack2x16Float) {
HasSubstr("f16tof32(uint2(tint_tmp & 0xffff, tint_tmp >> 16))")); HasSubstr("f16tof32(uint2(tint_tmp & 0xffff, tint_tmp >> 16))"));
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, StorageBarrier) { TEST_F(GlslGeneratorImplTest_Builtin, StorageBarrier) {
Func("main", {}, ty.void_(), Func("main", {}, ty.void_(),
{CallStmt(Call("storageBarrier"))}, {CallStmt(Call("storageBarrier"))},
{ {
@ -671,7 +664,7 @@ void main() {
)"); )");
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, WorkgroupBarrier) { TEST_F(GlslGeneratorImplTest_Builtin, WorkgroupBarrier) {
Func("main", {}, ty.void_(), Func("main", {}, ty.void_(),
{CallStmt(Call("workgroupBarrier"))}, {CallStmt(Call("workgroupBarrier"))},
{ {
@ -692,7 +685,7 @@ void main() {
#endif #endif
TEST_F(GlslGeneratorImplTest_Intrinsic, DotI32) { TEST_F(GlslGeneratorImplTest_Builtin, DotI32) {
Global("v", ty.vec3<i32>(), ast::StorageClass::kPrivate); Global("v", ty.vec3<i32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(Call("dot", "v", "v"))); WrapInFunction(CallStmt(Call("dot", "v", "v")));
@ -719,7 +712,7 @@ void main() {
)"); )");
} }
TEST_F(GlslGeneratorImplTest_Intrinsic, DotU32) { TEST_F(GlslGeneratorImplTest_Builtin, DotU32) {
Global("v", ty.vec3<u32>(), ast::StorageClass::kPrivate); Global("v", ty.vec3<u32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(Call("dot", "v", "v"))); WrapInFunction(CallStmt(Call("dot", "v", "v")));

View File

@ -13,8 +13,8 @@
// limitations under the License. // limitations under the License.
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "src/ast/builtin_texture_helper_test.h"
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/intrinsic_texture_helper_test.h"
#include "src/ast/stage_attribute.h" #include "src/ast/stage_attribute.h"
#include "src/writer/glsl/test_helper.h" #include "src/writer/glsl/test_helper.h"
@ -33,8 +33,8 @@ struct ExpectedResult {
}; };
ExpectedResult expected_texture_overload( ExpectedResult expected_texture_overload(
ast::intrinsic::test::ValidTextureOverload overload) { ast::builtin::test::ValidTextureOverload overload) {
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload; using ValidTextureOverload = ast::builtin::test::ValidTextureOverload;
switch (overload) { switch (overload) {
case ValidTextureOverload::kDimensions1d: case ValidTextureOverload::kDimensions1d:
case ValidTextureOverload::kDimensions2d: case ValidTextureOverload::kDimensions2d:
@ -267,10 +267,10 @@ ExpectedResult expected_texture_overload(
return "<unmatched texture overload>"; return "<unmatched texture overload>";
} // NOLINT - Ignore the length of this function } // NOLINT - Ignore the length of this function
class GlslGeneratorIntrinsicTextureTest class GlslGeneratorBuiltinTextureTest
: public TestParamHelper<ast::intrinsic::test::TextureOverloadCase> {}; : public TestParamHelper<ast::builtin::test::TextureOverloadCase> {};
TEST_P(GlslGeneratorIntrinsicTextureTest, Call) { TEST_P(GlslGeneratorBuiltinTextureTest, Call) {
auto param = GetParam(); auto param = GetParam();
param.BuildTextureVariable(this); param.BuildTextureVariable(this);
@ -292,9 +292,9 @@ TEST_P(GlslGeneratorIntrinsicTextureTest, Call) {
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
GlslGeneratorIntrinsicTextureTest, GlslGeneratorBuiltinTextureTest,
GlslGeneratorIntrinsicTextureTest, GlslGeneratorBuiltinTextureTest,
testing::ValuesIn(ast::intrinsic::test::TextureOverloadCase::ValidCases())); testing::ValuesIn(ast::builtin::test::TextureOverloadCase::ValidCases()));
} // namespace } // namespace
} // namespace glsl } // namespace glsl

View File

@ -933,8 +933,8 @@ bool GeneratorImpl::EmitCall(std::ostream& out,
if (auto* func = target->As<sem::Function>()) { if (auto* func = target->As<sem::Function>()) {
return EmitFunctionCall(out, call, func); return EmitFunctionCall(out, call, func);
} }
if (auto* intrinsic = target->As<sem::Intrinsic>()) { if (auto* builtin = target->As<sem::Builtin>()) {
return EmitIntrinsicCall(out, call, intrinsic); return EmitBuiltinCall(out, call, builtin);
} }
if (auto* conv = target->As<sem::TypeConversion>()) { if (auto* conv = target->As<sem::TypeConversion>()) {
return EmitTypeConversion(out, call, conv); return EmitTypeConversion(out, call, conv);
@ -1001,44 +1001,44 @@ bool GeneratorImpl::EmitFunctionCall(std::ostream& out,
return true; return true;
} }
bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out, bool GeneratorImpl::EmitBuiltinCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
auto* expr = call->Declaration(); auto* expr = call->Declaration();
if (intrinsic->IsTexture()) { if (builtin->IsTexture()) {
return EmitTextureCall(out, call, intrinsic); return EmitTextureCall(out, call, builtin);
} }
if (intrinsic->Type() == sem::IntrinsicType::kSelect) { if (builtin->Type() == sem::BuiltinType::kSelect) {
return EmitSelectCall(out, expr); return EmitSelectCall(out, expr);
} }
if (intrinsic->Type() == sem::IntrinsicType::kModf) { if (builtin->Type() == sem::BuiltinType::kModf) {
return EmitModfCall(out, expr, intrinsic); return EmitModfCall(out, expr, builtin);
} }
if (intrinsic->Type() == sem::IntrinsicType::kFrexp) { if (builtin->Type() == sem::BuiltinType::kFrexp) {
return EmitFrexpCall(out, expr, intrinsic); return EmitFrexpCall(out, expr, builtin);
} }
if (intrinsic->Type() == sem::IntrinsicType::kIsNormal) { if (builtin->Type() == sem::BuiltinType::kIsNormal) {
return EmitIsNormalCall(out, expr, intrinsic); return EmitIsNormalCall(out, expr, builtin);
} }
if (intrinsic->Type() == sem::IntrinsicType::kDegrees) { if (builtin->Type() == sem::BuiltinType::kDegrees) {
return EmitDegreesCall(out, expr, intrinsic); return EmitDegreesCall(out, expr, builtin);
} }
if (intrinsic->Type() == sem::IntrinsicType::kRadians) { if (builtin->Type() == sem::BuiltinType::kRadians) {
return EmitRadiansCall(out, expr, intrinsic); return EmitRadiansCall(out, expr, builtin);
} }
if (intrinsic->IsDataPacking()) { if (builtin->IsDataPacking()) {
return EmitDataPackingCall(out, expr, intrinsic); return EmitDataPackingCall(out, expr, builtin);
} }
if (intrinsic->IsDataUnpacking()) { if (builtin->IsDataUnpacking()) {
return EmitDataUnpackingCall(out, expr, intrinsic); return EmitDataUnpackingCall(out, expr, builtin);
} }
if (intrinsic->IsBarrier()) { if (builtin->IsBarrier()) {
return EmitBarrierCall(out, intrinsic); return EmitBarrierCall(out, builtin);
} }
if (intrinsic->IsAtomic()) { if (builtin->IsAtomic()) {
return EmitWorkgroupAtomicCall(out, expr, intrinsic); return EmitWorkgroupAtomicCall(out, expr, builtin);
} }
auto name = generate_builtin_name(intrinsic); auto name = generate_builtin_name(builtin);
if (name.empty()) { if (name.empty()) {
return false; return false;
} }
@ -1637,17 +1637,17 @@ bool GeneratorImpl::EmitStorageAtomicCall(
bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out, bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
std::string result = UniqueIdentifier("atomic_result"); std::string result = UniqueIdentifier("atomic_result");
if (!intrinsic->ReturnType()->Is<sem::Void>()) { if (!builtin->ReturnType()->Is<sem::Void>()) {
auto pre = line(); auto pre = line();
if (!EmitTypeAndName(pre, intrinsic->ReturnType(), ast::StorageClass::kNone, if (!EmitTypeAndName(pre, builtin->ReturnType(), ast::StorageClass::kNone,
ast::Access::kUndefined, result)) { ast::Access::kUndefined, result)) {
return false; return false;
} }
pre << " = "; pre << " = ";
if (!EmitZeroValue(pre, intrinsic->ReturnType())) { if (!EmitZeroValue(pre, builtin->ReturnType())) {
return false; return false;
} }
pre << ";"; pre << ";";
@ -1664,7 +1664,7 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
if (i > 0) { if (i > 0) {
pre << ", "; pre << ", ";
} }
if (i == 1 && intrinsic->Type() == sem::IntrinsicType::kAtomicSub) { if (i == 1 && builtin->Type() == sem::BuiltinType::kAtomicSub) {
// Sub uses InterlockedAdd with the operand negated. // Sub uses InterlockedAdd with the operand negated.
pre << "-"; pre << "-";
} }
@ -1682,8 +1682,8 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
return true; return true;
}; };
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kAtomicLoad: { case sem::BuiltinType::kAtomicLoad: {
// HLSL does not have an InterlockedLoad, so we emulate it with // HLSL does not have an InterlockedLoad, so we emulate it with
// InterlockedOr using 0 as the OR value // InterlockedOr using 0 as the OR value
auto pre = line(); auto pre = line();
@ -1700,12 +1700,12 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
out << result; out << result;
return true; return true;
} }
case sem::IntrinsicType::kAtomicStore: { case sem::BuiltinType::kAtomicStore: {
// HLSL does not have an InterlockedStore, so we emulate it with // HLSL does not have an InterlockedStore, so we emulate it with
// InterlockedExchange and discard the returned value // InterlockedExchange and discard the returned value
{ // T result = 0; { // T result = 0;
auto pre = line(); auto pre = line();
auto* value_ty = intrinsic->Parameters()[1]->Type()->UnwrapRef(); auto* value_ty = builtin->Parameters()[1]->Type()->UnwrapRef();
if (!EmitTypeAndName(pre, value_ty, ast::StorageClass::kNone, if (!EmitTypeAndName(pre, value_ty, ast::StorageClass::kNone,
ast::Access::kUndefined, result)) { ast::Access::kUndefined, result)) {
return false; return false;
@ -1731,7 +1731,7 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
} }
return true; return true;
} }
case sem::IntrinsicType::kAtomicCompareExchangeWeak: { case sem::BuiltinType::kAtomicCompareExchangeWeak: {
auto* dest = expr->args[0]; auto* dest = expr->args[0];
auto* compare_value = expr->args[1]; auto* compare_value = expr->args[1];
auto* value = expr->args[2]; auto* value = expr->args[2];
@ -1777,26 +1777,26 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
return true; return true;
} }
case sem::IntrinsicType::kAtomicAdd: case sem::BuiltinType::kAtomicAdd:
case sem::IntrinsicType::kAtomicSub: case sem::BuiltinType::kAtomicSub:
return call("InterlockedAdd"); return call("InterlockedAdd");
case sem::IntrinsicType::kAtomicMax: case sem::BuiltinType::kAtomicMax:
return call("InterlockedMax"); return call("InterlockedMax");
case sem::IntrinsicType::kAtomicMin: case sem::BuiltinType::kAtomicMin:
return call("InterlockedMin"); return call("InterlockedMin");
case sem::IntrinsicType::kAtomicAnd: case sem::BuiltinType::kAtomicAnd:
return call("InterlockedAnd"); return call("InterlockedAnd");
case sem::IntrinsicType::kAtomicOr: case sem::BuiltinType::kAtomicOr:
return call("InterlockedOr"); return call("InterlockedOr");
case sem::IntrinsicType::kAtomicXor: case sem::BuiltinType::kAtomicXor:
return call("InterlockedXor"); return call("InterlockedXor");
case sem::IntrinsicType::kAtomicExchange: case sem::BuiltinType::kAtomicExchange:
return call("InterlockedExchange"); return call("InterlockedExchange");
default: default:
@ -1804,7 +1804,7 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
} }
TINT_UNREACHABLE(Writer, diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported atomic intrinsic: " << intrinsic->Type(); << "unsupported atomic builtin: " << builtin->Type();
return false; return false;
} }
@ -1835,11 +1835,11 @@ bool GeneratorImpl::EmitSelectCall(std::ostream& out,
bool GeneratorImpl::EmitModfCall(std::ostream& out, bool GeneratorImpl::EmitModfCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
auto* ty = intrinsic->Parameters()[0]->Type(); auto* ty = builtin->Parameters()[0]->Type();
auto in = params[0]; auto in = params[0];
std::string width; std::string width;
@ -1850,7 +1850,7 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
// Emit the builtin return type unique to this overload. This does not // Emit the builtin return type unique to this overload. This does not
// exist in the AST, so it will not be generated in Generate(). // exist in the AST, so it will not be generated in Generate().
if (!EmitStructType(&helpers_, if (!EmitStructType(&helpers_,
intrinsic->ReturnType()->As<sem::Struct>())) { builtin->ReturnType()->As<sem::Struct>())) {
return false; return false;
} }
@ -1858,7 +1858,7 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
line(b) << "float" << width << " fract = modf(" << in << ", whole);"; line(b) << "float" << width << " fract = modf(" << in << ", whole);";
{ {
auto l = line(b); auto l = line(b);
if (!EmitType(l, intrinsic->ReturnType(), ast::StorageClass::kNone, if (!EmitType(l, builtin->ReturnType(), ast::StorageClass::kNone,
ast::Access::kUndefined, "")) { ast::Access::kUndefined, "")) {
return false; return false;
} }
@ -1871,11 +1871,11 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
bool GeneratorImpl::EmitFrexpCall(std::ostream& out, bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
auto* ty = intrinsic->Parameters()[0]->Type(); auto* ty = builtin->Parameters()[0]->Type();
auto in = params[0]; auto in = params[0];
std::string width; std::string width;
@ -1886,7 +1886,7 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
// Emit the builtin return type unique to this overload. This does not // Emit the builtin return type unique to this overload. This does not
// exist in the AST, so it will not be generated in Generate(). // exist in the AST, so it will not be generated in Generate().
if (!EmitStructType(&helpers_, if (!EmitStructType(&helpers_,
intrinsic->ReturnType()->As<sem::Struct>())) { builtin->ReturnType()->As<sem::Struct>())) {
return false; return false;
} }
@ -1894,7 +1894,7 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
line(b) << "float" << width << " sig = frexp(" << in << ", exp);"; line(b) << "float" << width << " sig = frexp(" << in << ", exp);";
{ {
auto l = line(b); auto l = line(b);
if (!EmitType(l, intrinsic->ReturnType(), ast::StorageClass::kNone, if (!EmitType(l, builtin->ReturnType(), ast::StorageClass::kNone,
ast::Access::kUndefined, "")) { ast::Access::kUndefined, "")) {
return false; return false;
} }
@ -1907,12 +1907,12 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
bool GeneratorImpl::EmitIsNormalCall(std::ostream& out, bool GeneratorImpl::EmitIsNormalCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
// HLSL doesn't have a isNormal intrinsic, we need to emulate // HLSL doesn't have a isNormal builtin, we need to emulate
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
auto* input_ty = intrinsic->Parameters()[0]->Type(); auto* input_ty = builtin->Parameters()[0]->Type();
std::string width; std::string width;
if (auto* vec = input_ty->As<sem::Vector>()) { if (auto* vec = input_ty->As<sem::Vector>()) {
@ -1935,9 +1935,9 @@ bool GeneratorImpl::EmitIsNormalCall(std::ostream& out,
bool GeneratorImpl::EmitDegreesCall(std::ostream& out, bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
line(b) << "return " << params[0] << " * " << std::setprecision(20) line(b) << "return " << params[0] << " * " << std::setprecision(20)
<< sem::kRadToDeg << ";"; << sem::kRadToDeg << ";";
@ -1947,9 +1947,9 @@ bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
bool GeneratorImpl::EmitRadiansCall(std::ostream& out, bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
line(b) << "return " << params[0] << " * " << std::setprecision(20) line(b) << "return " << params[0] << " * " << std::setprecision(20)
<< sem::kDegToRad << ";"; << sem::kDegToRad << ";";
@ -1959,28 +1959,28 @@ bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
bool GeneratorImpl::EmitDataPackingCall(std::ostream& out, bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
uint32_t dims = 2; uint32_t dims = 2;
bool is_signed = false; bool is_signed = false;
uint32_t scale = 65535; uint32_t scale = 65535;
if (intrinsic->Type() == sem::IntrinsicType::kPack4x8snorm || if (builtin->Type() == sem::BuiltinType::kPack4x8snorm ||
intrinsic->Type() == sem::IntrinsicType::kPack4x8unorm) { builtin->Type() == sem::BuiltinType::kPack4x8unorm) {
dims = 4; dims = 4;
scale = 255; scale = 255;
} }
if (intrinsic->Type() == sem::IntrinsicType::kPack4x8snorm || if (builtin->Type() == sem::BuiltinType::kPack4x8snorm ||
intrinsic->Type() == sem::IntrinsicType::kPack2x16snorm) { builtin->Type() == sem::BuiltinType::kPack2x16snorm) {
is_signed = true; is_signed = true;
scale = (scale - 1) / 2; scale = (scale - 1) / 2;
} }
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kPack4x8snorm: case sem::BuiltinType::kPack4x8snorm:
case sem::IntrinsicType::kPack4x8unorm: case sem::BuiltinType::kPack4x8unorm:
case sem::IntrinsicType::kPack2x16snorm: case sem::BuiltinType::kPack2x16snorm:
case sem::IntrinsicType::kPack2x16unorm: { case sem::BuiltinType::kPack2x16unorm: {
{ {
auto l = line(b); auto l = line(b);
l << (is_signed ? "" : "u") << "int" << dims l << (is_signed ? "" : "u") << "int" << dims
@ -2007,7 +2007,7 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
} }
break; break;
} }
case sem::IntrinsicType::kPack2x16float: { case sem::BuiltinType::kPack2x16float: {
line(b) << "uint2 i = f32tof16(" << params[0] << ");"; line(b) << "uint2 i = f32tof16(" << params[0] << ");";
line(b) << "return i.x | (i.y << 16);"; line(b) << "return i.x | (i.y << 16);";
break; break;
@ -2015,7 +2015,7 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
default: default:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer, diag::System::Writer,
"Internal error: unhandled data packing intrinsic"); "Internal error: unhandled data packing builtin");
return false; return false;
} }
@ -2025,26 +2025,26 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out, bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
uint32_t dims = 2; uint32_t dims = 2;
bool is_signed = false; bool is_signed = false;
uint32_t scale = 65535; uint32_t scale = 65535;
if (intrinsic->Type() == sem::IntrinsicType::kUnpack4x8snorm || if (builtin->Type() == sem::BuiltinType::kUnpack4x8snorm ||
intrinsic->Type() == sem::IntrinsicType::kUnpack4x8unorm) { builtin->Type() == sem::BuiltinType::kUnpack4x8unorm) {
dims = 4; dims = 4;
scale = 255; scale = 255;
} }
if (intrinsic->Type() == sem::IntrinsicType::kUnpack4x8snorm || if (builtin->Type() == sem::BuiltinType::kUnpack4x8snorm ||
intrinsic->Type() == sem::IntrinsicType::kUnpack2x16snorm) { builtin->Type() == sem::BuiltinType::kUnpack2x16snorm) {
is_signed = true; is_signed = true;
scale = (scale - 1) / 2; scale = (scale - 1) / 2;
} }
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kUnpack4x8snorm: case sem::BuiltinType::kUnpack4x8snorm:
case sem::IntrinsicType::kUnpack2x16snorm: { case sem::BuiltinType::kUnpack2x16snorm: {
line(b) << "int j = int(" << params[0] << ");"; line(b) << "int j = int(" << params[0] << ");";
{ // Perform sign extension on the converted values. { // Perform sign extension on the converted values.
auto l = line(b); auto l = line(b);
@ -2060,8 +2060,8 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
<< ".0, " << (is_signed ? "-1.0" : "0.0") << ", 1.0);"; << ".0, " << (is_signed ? "-1.0" : "0.0") << ", 1.0);";
break; break;
} }
case sem::IntrinsicType::kUnpack4x8unorm: case sem::BuiltinType::kUnpack4x8unorm:
case sem::IntrinsicType::kUnpack2x16unorm: { case sem::BuiltinType::kUnpack2x16unorm: {
line(b) << "uint j = " << params[0] << ";"; line(b) << "uint j = " << params[0] << ";";
{ {
auto l = line(b); auto l = line(b);
@ -2078,14 +2078,14 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
line(b) << "return float" << dims << "(i) / " << scale << ".0;"; line(b) << "return float" << dims << "(i) / " << scale << ".0;";
break; break;
} }
case sem::IntrinsicType::kUnpack2x16float: case sem::BuiltinType::kUnpack2x16float:
line(b) << "uint i = " << params[0] << ";"; line(b) << "uint i = " << params[0] << ";";
line(b) << "return f16tof32(uint2(i & 0xffff, i >> 16));"; line(b) << "return f16tof32(uint2(i & 0xffff, i >> 16));";
break; break;
default: default:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer, diag::System::Writer,
"Internal error: unhandled data packing intrinsic"); "Internal error: unhandled data packing builtin");
return false; return false;
} }
@ -2094,16 +2094,16 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
} }
bool GeneratorImpl::EmitBarrierCall(std::ostream& out, bool GeneratorImpl::EmitBarrierCall(std::ostream& out,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
// TODO(crbug.com/tint/661): Combine sequential barriers to a single // TODO(crbug.com/tint/661): Combine sequential barriers to a single
// instruction. // instruction.
if (intrinsic->Type() == sem::IntrinsicType::kWorkgroupBarrier) { if (builtin->Type() == sem::BuiltinType::kWorkgroupBarrier) {
out << "GroupMemoryBarrierWithGroupSync()"; out << "GroupMemoryBarrierWithGroupSync()";
} else if (intrinsic->Type() == sem::IntrinsicType::kStorageBarrier) { } else if (builtin->Type() == sem::BuiltinType::kStorageBarrier) {
out << "DeviceMemoryBarrierWithGroupSync()"; out << "DeviceMemoryBarrierWithGroupSync()";
} else { } else {
TINT_UNREACHABLE(Writer, diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unexpected barrier intrinsic type " << sem::str(intrinsic->Type()); << "unexpected barrier builtin type " << sem::str(builtin->Type());
return false; return false;
} }
return true; return true;
@ -2111,10 +2111,10 @@ bool GeneratorImpl::EmitBarrierCall(std::ostream& out,
bool GeneratorImpl::EmitTextureCall(std::ostream& out, bool GeneratorImpl::EmitTextureCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
using Usage = sem::ParameterUsage; using Usage = sem::ParameterUsage;
auto& signature = intrinsic->Signature(); auto& signature = builtin->Signature();
auto* expr = call->Declaration(); auto* expr = call->Declaration();
auto arguments = expr->args; auto arguments = expr->args;
@ -2132,19 +2132,19 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
auto* texture_type = TypeOf(texture)->UnwrapRef()->As<sem::Texture>(); auto* texture_type = TypeOf(texture)->UnwrapRef()->As<sem::Texture>();
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kTextureDimensions: case sem::BuiltinType::kTextureDimensions:
case sem::IntrinsicType::kTextureNumLayers: case sem::BuiltinType::kTextureNumLayers:
case sem::IntrinsicType::kTextureNumLevels: case sem::BuiltinType::kTextureNumLevels:
case sem::IntrinsicType::kTextureNumSamples: { case sem::BuiltinType::kTextureNumSamples: {
// All of these intrinsics use the GetDimensions() method on the texture // All of these builtins use the GetDimensions() method on the texture
bool is_ms = texture_type->IsAnyOf<sem::MultisampledTexture, bool is_ms = texture_type->IsAnyOf<sem::MultisampledTexture,
sem::DepthMultisampledTexture>(); sem::DepthMultisampledTexture>();
int num_dimensions = 0; int num_dimensions = 0;
std::string swizzle; std::string swizzle;
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kTextureDimensions: case sem::BuiltinType::kTextureDimensions:
switch (texture_type->dim()) { switch (texture_type->dim()) {
case ast::TextureDimension::kNone: case ast::TextureDimension::kNone:
TINT_ICE(Writer, diagnostics_) << "texture dimension is kNone"; TINT_ICE(Writer, diagnostics_) << "texture dimension is kNone";
@ -2172,7 +2172,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
break; break;
} }
break; break;
case sem::IntrinsicType::kTextureNumLayers: case sem::BuiltinType::kTextureNumLayers:
switch (texture_type->dim()) { switch (texture_type->dim()) {
default: default:
TINT_ICE(Writer, diagnostics_) TINT_ICE(Writer, diagnostics_)
@ -2188,7 +2188,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
break; break;
} }
break; break;
case sem::IntrinsicType::kTextureNumLevels: case sem::BuiltinType::kTextureNumLevels:
switch (texture_type->dim()) { switch (texture_type->dim()) {
default: default:
TINT_ICE(Writer, diagnostics_) TINT_ICE(Writer, diagnostics_)
@ -2211,7 +2211,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
break; break;
} }
break; break;
case sem::IntrinsicType::kTextureNumSamples: case sem::BuiltinType::kTextureNumSamples:
switch (texture_type->dim()) { switch (texture_type->dim()) {
default: default:
TINT_ICE(Writer, diagnostics_) TINT_ICE(Writer, diagnostics_)
@ -2228,7 +2228,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
} }
break; break;
default: default:
TINT_ICE(Writer, diagnostics_) << "unexpected intrinsic"; TINT_ICE(Writer, diagnostics_) << "unexpected builtin";
return false; return false;
} }
@ -2251,7 +2251,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
if (num_dimensions > 4) { if (num_dimensions > 4) {
TINT_ICE(Writer, diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "Texture query intrinsic temporary vector has " << num_dimensions << "Texture query builtin temporary vector has " << num_dimensions
<< " dimensions"; << " dimensions";
return false; return false;
} }
@ -2276,7 +2276,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
return false; return false;
} }
pre << ", "; pre << ", ";
} else if (intrinsic->Type() == sem::IntrinsicType::kTextureNumLevels) { } else if (builtin->Type() == sem::BuiltinType::kTextureNumLevels) {
pre << "0, "; pre << "0, ";
} }
@ -2314,44 +2314,44 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
return false; return false;
// If pack_level_in_coords is true, then the mip level will be appended as the // If pack_level_in_coords is true, then the mip level will be appended as the
// last value of the coordinates argument. If the WGSL intrinsic overload does // last value of the coordinates argument. If the WGSL builtin overload does
// not have a level parameter and pack_level_in_coords is true, then a zero // not have a level parameter and pack_level_in_coords is true, then a zero
// mip level will be inserted. // mip level will be inserted.
bool pack_level_in_coords = false; bool pack_level_in_coords = false;
uint32_t hlsl_ret_width = 4u; uint32_t hlsl_ret_width = 4u;
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kTextureSample: case sem::BuiltinType::kTextureSample:
out << ".Sample("; out << ".Sample(";
break; break;
case sem::IntrinsicType::kTextureSampleBias: case sem::BuiltinType::kTextureSampleBias:
out << ".SampleBias("; out << ".SampleBias(";
break; break;
case sem::IntrinsicType::kTextureSampleLevel: case sem::BuiltinType::kTextureSampleLevel:
out << ".SampleLevel("; out << ".SampleLevel(";
break; break;
case sem::IntrinsicType::kTextureSampleGrad: case sem::BuiltinType::kTextureSampleGrad:
out << ".SampleGrad("; out << ".SampleGrad(";
break; break;
case sem::IntrinsicType::kTextureSampleCompare: case sem::BuiltinType::kTextureSampleCompare:
out << ".SampleCmp("; out << ".SampleCmp(";
hlsl_ret_width = 1; hlsl_ret_width = 1;
break; break;
case sem::IntrinsicType::kTextureSampleCompareLevel: case sem::BuiltinType::kTextureSampleCompareLevel:
out << ".SampleCmpLevelZero("; out << ".SampleCmpLevelZero(";
hlsl_ret_width = 1; hlsl_ret_width = 1;
break; break;
case sem::IntrinsicType::kTextureLoad: case sem::BuiltinType::kTextureLoad:
out << ".Load("; out << ".Load(";
// Multisampled textures do not support mip-levels. // Multisampled textures do not support mip-levels.
if (!texture_type->Is<sem::MultisampledTexture>()) { if (!texture_type->Is<sem::MultisampledTexture>()) {
pack_level_in_coords = true; pack_level_in_coords = true;
} }
break; break;
case sem::IntrinsicType::kTextureGather: case sem::BuiltinType::kTextureGather:
out << ".Gather"; out << ".Gather";
if (intrinsic->Parameters()[0]->Usage() == if (builtin->Parameters()[0]->Usage() ==
sem::ParameterUsage::kComponent) { sem::ParameterUsage::kComponent) {
switch (call->Arguments()[0]->ConstantValue().Elements()[0].i32) { switch (call->Arguments()[0]->ConstantValue().Elements()[0].i32) {
case 0: case 0:
@ -2370,17 +2370,17 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
} }
out << "("; out << "(";
break; break;
case sem::IntrinsicType::kTextureGatherCompare: case sem::BuiltinType::kTextureGatherCompare:
out << ".GatherCmp("; out << ".GatherCmp(";
break; break;
case sem::IntrinsicType::kTextureStore: case sem::BuiltinType::kTextureStore:
out << "["; out << "[";
break; break;
default: default:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer, diag::System::Writer,
"Internal compiler error: Unhandled texture intrinsic '" + "Internal compiler error: Unhandled texture builtin '" +
std::string(intrinsic->str()) + "'"); std::string(builtin->str()) + "'");
return false; return false;
} }
@ -2451,7 +2451,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
} }
} }
if (intrinsic->Type() == sem::IntrinsicType::kTextureStore) { if (builtin->Type() == sem::BuiltinType::kTextureStore) {
out << "] = "; out << "] = ";
if (!EmitExpression(out, arg(Usage::kValue))) { if (!EmitExpression(out, arg(Usage::kValue))) {
return false; return false;
@ -2459,11 +2459,11 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
} else { } else {
out << ")"; out << ")";
// If the intrinsic return type does not match the number of elements of the // If the builtin return type does not match the number of elements of the
// HLSL intrinsic, we need to swizzle the expression to generate the correct // HLSL builtin, we need to swizzle the expression to generate the correct
// number of components. // number of components.
uint32_t wgsl_ret_width = 1; uint32_t wgsl_ret_width = 1;
if (auto* vec = intrinsic->ReturnType()->As<sem::Vector>()) { if (auto* vec = builtin->ReturnType()->As<sem::Vector>()) {
wgsl_ret_width = vec->Width(); wgsl_ret_width = vec->Width();
} }
if (wgsl_ret_width < hlsl_ret_width) { if (wgsl_ret_width < hlsl_ret_width) {
@ -2476,7 +2476,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
TINT_ICE(Writer, diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "WGSL return width (" << wgsl_ret_width << "WGSL return width (" << wgsl_ret_width
<< ") is wider than HLSL return width (" << hlsl_ret_width << ") for " << ") is wider than HLSL return width (" << hlsl_ret_width << ") for "
<< intrinsic->Type(); << builtin->Type();
return false; return false;
} }
} }
@ -2484,92 +2484,91 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
return true; return true;
} }
std::string GeneratorImpl::generate_builtin_name( std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
const sem::Intrinsic* intrinsic) { switch (builtin->Type()) {
switch (intrinsic->Type()) { case sem::BuiltinType::kAbs:
case sem::IntrinsicType::kAbs: case sem::BuiltinType::kAcos:
case sem::IntrinsicType::kAcos: case sem::BuiltinType::kAll:
case sem::IntrinsicType::kAll: case sem::BuiltinType::kAny:
case sem::IntrinsicType::kAny: case sem::BuiltinType::kAsin:
case sem::IntrinsicType::kAsin: case sem::BuiltinType::kAtan:
case sem::IntrinsicType::kAtan: case sem::BuiltinType::kAtan2:
case sem::IntrinsicType::kAtan2: case sem::BuiltinType::kCeil:
case sem::IntrinsicType::kCeil: case sem::BuiltinType::kClamp:
case sem::IntrinsicType::kClamp: case sem::BuiltinType::kCos:
case sem::IntrinsicType::kCos: case sem::BuiltinType::kCosh:
case sem::IntrinsicType::kCosh: case sem::BuiltinType::kCross:
case sem::IntrinsicType::kCross: case sem::BuiltinType::kDeterminant:
case sem::IntrinsicType::kDeterminant: case sem::BuiltinType::kDistance:
case sem::IntrinsicType::kDistance: case sem::BuiltinType::kDot:
case sem::IntrinsicType::kDot: case sem::BuiltinType::kExp:
case sem::IntrinsicType::kExp: case sem::BuiltinType::kExp2:
case sem::IntrinsicType::kExp2: case sem::BuiltinType::kFloor:
case sem::IntrinsicType::kFloor: case sem::BuiltinType::kFrexp:
case sem::IntrinsicType::kFrexp: case sem::BuiltinType::kLdexp:
case sem::IntrinsicType::kLdexp: case sem::BuiltinType::kLength:
case sem::IntrinsicType::kLength: case sem::BuiltinType::kLog:
case sem::IntrinsicType::kLog: case sem::BuiltinType::kLog2:
case sem::IntrinsicType::kLog2: case sem::BuiltinType::kMax:
case sem::IntrinsicType::kMax: case sem::BuiltinType::kMin:
case sem::IntrinsicType::kMin: case sem::BuiltinType::kModf:
case sem::IntrinsicType::kModf: case sem::BuiltinType::kNormalize:
case sem::IntrinsicType::kNormalize: case sem::BuiltinType::kPow:
case sem::IntrinsicType::kPow: case sem::BuiltinType::kReflect:
case sem::IntrinsicType::kReflect: case sem::BuiltinType::kRefract:
case sem::IntrinsicType::kRefract: case sem::BuiltinType::kRound:
case sem::IntrinsicType::kRound: case sem::BuiltinType::kSign:
case sem::IntrinsicType::kSign: case sem::BuiltinType::kSin:
case sem::IntrinsicType::kSin: case sem::BuiltinType::kSinh:
case sem::IntrinsicType::kSinh: case sem::BuiltinType::kSqrt:
case sem::IntrinsicType::kSqrt: case sem::BuiltinType::kStep:
case sem::IntrinsicType::kStep: case sem::BuiltinType::kTan:
case sem::IntrinsicType::kTan: case sem::BuiltinType::kTanh:
case sem::IntrinsicType::kTanh: case sem::BuiltinType::kTranspose:
case sem::IntrinsicType::kTranspose: case sem::BuiltinType::kTrunc:
case sem::IntrinsicType::kTrunc: return builtin->str();
return intrinsic->str(); case sem::BuiltinType::kCountOneBits:
case sem::IntrinsicType::kCountOneBits:
return "countbits"; return "countbits";
case sem::IntrinsicType::kDpdx: case sem::BuiltinType::kDpdx:
return "ddx"; return "ddx";
case sem::IntrinsicType::kDpdxCoarse: case sem::BuiltinType::kDpdxCoarse:
return "ddx_coarse"; return "ddx_coarse";
case sem::IntrinsicType::kDpdxFine: case sem::BuiltinType::kDpdxFine:
return "ddx_fine"; return "ddx_fine";
case sem::IntrinsicType::kDpdy: case sem::BuiltinType::kDpdy:
return "ddy"; return "ddy";
case sem::IntrinsicType::kDpdyCoarse: case sem::BuiltinType::kDpdyCoarse:
return "ddy_coarse"; return "ddy_coarse";
case sem::IntrinsicType::kDpdyFine: case sem::BuiltinType::kDpdyFine:
return "ddy_fine"; return "ddy_fine";
case sem::IntrinsicType::kFaceForward: case sem::BuiltinType::kFaceForward:
return "faceforward"; return "faceforward";
case sem::IntrinsicType::kFract: case sem::BuiltinType::kFract:
return "frac"; return "frac";
case sem::IntrinsicType::kFma: case sem::BuiltinType::kFma:
return "mad"; return "mad";
case sem::IntrinsicType::kFwidth: case sem::BuiltinType::kFwidth:
case sem::IntrinsicType::kFwidthCoarse: case sem::BuiltinType::kFwidthCoarse:
case sem::IntrinsicType::kFwidthFine: case sem::BuiltinType::kFwidthFine:
return "fwidth"; return "fwidth";
case sem::IntrinsicType::kInverseSqrt: case sem::BuiltinType::kInverseSqrt:
return "rsqrt"; return "rsqrt";
case sem::IntrinsicType::kIsFinite: case sem::BuiltinType::kIsFinite:
return "isfinite"; return "isfinite";
case sem::IntrinsicType::kIsInf: case sem::BuiltinType::kIsInf:
return "isinf"; return "isinf";
case sem::IntrinsicType::kIsNan: case sem::BuiltinType::kIsNan:
return "isnan"; return "isnan";
case sem::IntrinsicType::kMix: case sem::BuiltinType::kMix:
return "lerp"; return "lerp";
case sem::IntrinsicType::kReverseBits: case sem::BuiltinType::kReverseBits:
return "reversebits"; return "reversebits";
case sem::IntrinsicType::kSmoothStep: case sem::BuiltinType::kSmoothStep:
return "smoothstep"; return "smoothstep";
default: default:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer, diag::System::Writer,
"Unknown builtin method: " + std::string(intrinsic->str())); "Unknown builtin method: " + std::string(builtin->str()));
} }
return ""; return "";
@ -3892,28 +3891,28 @@ bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
} }
template <typename F> template <typename F>
bool GeneratorImpl::CallIntrinsicHelper(std::ostream& out, bool GeneratorImpl::CallBuiltinHelper(std::ostream& out,
const ast::CallExpression* call, const ast::CallExpression* call,
const sem::Intrinsic* intrinsic, const sem::Builtin* builtin,
F&& build) { F&& build) {
// Generate the helper function if it hasn't been created already // Generate the helper function if it hasn't been created already
auto fn = utils::GetOrCreate(intrinsics_, intrinsic, [&]() -> std::string { auto fn = utils::GetOrCreate(builtins_, builtin, [&]() -> std::string {
TextBuffer b; TextBuffer b;
TINT_DEFER(helpers_.Append(b)); TINT_DEFER(helpers_.Append(b));
auto fn_name = auto fn_name =
UniqueIdentifier(std::string("tint_") + sem::str(intrinsic->Type())); UniqueIdentifier(std::string("tint_") + sem::str(builtin->Type()));
std::vector<std::string> parameter_names; std::vector<std::string> parameter_names;
{ {
auto decl = line(&b); auto decl = line(&b);
if (!EmitTypeAndName(decl, intrinsic->ReturnType(), if (!EmitTypeAndName(decl, builtin->ReturnType(),
ast::StorageClass::kNone, ast::Access::kUndefined, ast::StorageClass::kNone, ast::Access::kUndefined,
fn_name)) { fn_name)) {
return ""; return "";
} }
{ {
ScopedParen sp(decl); ScopedParen sp(decl);
for (auto* param : intrinsic->Parameters()) { for (auto* param : builtin->Parameters()) {
if (!parameter_names.empty()) { if (!parameter_names.empty()) {
decl << ", "; decl << ", ";
} }

View File

@ -44,7 +44,7 @@ namespace tint {
// Forward declarations // Forward declarations
namespace sem { namespace sem {
class Call; class Call;
class Intrinsic; class Builtin;
class TypeConstructor; class TypeConstructor;
class TypeConversion; class TypeConversion;
} // namespace sem } // namespace sem
@ -145,14 +145,14 @@ class GeneratorImpl : public TextGenerator {
bool EmitFunctionCall(std::ostream& out, bool EmitFunctionCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Function* function); const sem::Function* function);
/// Handles generating an intrinsic call expression /// Handles generating a builtin call expression
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
/// @param intrinsic the intrinsic being called /// @param builtin the builtin being called
/// @returns true if the expression is emitted /// @returns true if the expression is emitted
bool EmitIntrinsicCall(std::ostream& out, bool EmitBuiltinCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a type conversion expression /// Handles generating a type conversion expression
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
@ -191,9 +191,9 @@ class GeneratorImpl : public TextGenerator {
const transform::DecomposeMemoryAccess::Intrinsic* intrinsic); const transform::DecomposeMemoryAccess::Intrinsic* intrinsic);
/// Handles generating a barrier intrinsic call /// Handles generating a barrier intrinsic call
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param intrinsic the semantic information for the barrier intrinsic /// @param builtin the semantic information for the barrier builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitBarrierCall(std::ostream& out, const sem::Intrinsic* intrinsic); bool EmitBarrierCall(std::ostream& out, const sem::Builtin* builtin);
/// Handles generating an atomic intrinsic call for a storage buffer variable /// Handles generating an atomic intrinsic call for a storage buffer variable
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
@ -206,81 +206,81 @@ class GeneratorImpl : public TextGenerator {
/// Handles generating an atomic intrinsic call for a workgroup variable /// Handles generating an atomic intrinsic call for a workgroup variable
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the atomic intrinsic /// @param builtin the semantic information for the atomic builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitWorkgroupAtomicCall(std::ostream& out, bool EmitWorkgroupAtomicCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to a texture function (`textureSample`, /// Handles generating a call to a texture function (`textureSample`,
/// `textureSampleGrad`, etc) /// `textureSampleGrad`, etc)
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
/// @param intrinsic the semantic information for the texture intrinsic /// @param builtin the semantic information for the texture builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitTextureCall(std::ostream& out, bool EmitTextureCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `select()` intrinsic /// Handles generating a call to the `select()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitSelectCall(std::ostream& out, const ast::CallExpression* expr); bool EmitSelectCall(std::ostream& out, const ast::CallExpression* expr);
/// Handles generating a call to the `modf()` intrinsic /// Handles generating a call to the `modf()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitModfCall(std::ostream& out, bool EmitModfCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `frexp()` intrinsic /// Handles generating a call to the `frexp()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitFrexpCall(std::ostream& out, bool EmitFrexpCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `isNormal()` intrinsic /// Handles generating a call to the `isNormal()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitIsNormalCall(std::ostream& out, bool EmitIsNormalCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `degrees()` intrinsic /// Handles generating a call to the `degrees()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitDegreesCall(std::ostream& out, bool EmitDegreesCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `radians()` intrinsic /// Handles generating a call to the `radians()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitRadiansCall(std::ostream& out, bool EmitRadiansCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to data packing intrinsic /// Handles generating a call to data packing builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the texture intrinsic /// @param builtin the semantic information for the texture builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitDataPackingCall(std::ostream& out, bool EmitDataPackingCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to data unpacking intrinsic /// Handles generating a call to data unpacking builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the texture intrinsic /// @param builtin the semantic information for the texture builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitDataUnpackingCall(std::ostream& out, bool EmitDataUnpackingCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles a case statement /// Handles a case statement
/// @param s the switch statement /// @param s the switch statement
/// @param case_idx the index of the switch case in the switch statement /// @param case_idx the index of the switch case in the switch statement
@ -473,9 +473,9 @@ class GeneratorImpl : public TextGenerator {
const sem::Matrix* mat); const sem::Matrix* mat);
/// Handles generating a builtin method name /// Handles generating a builtin method name
/// @param intrinsic the semantic info for the intrinsic /// @param builtin the semantic info for the builtin
/// @returns the name or "" if not valid /// @returns the name or "" if not valid
std::string generate_builtin_name(const sem::Intrinsic* intrinsic); std::string generate_builtin_name(const sem::Builtin* builtin);
/// Converts a builtin to an attribute name /// Converts a builtin to an attribute name
/// @param builtin the builtin to convert /// @param builtin the builtin to convert
/// @returns the string name of the builtin or blank on error /// @returns the string name of the builtin or blank on error
@ -513,13 +513,13 @@ class GeneratorImpl : public TextGenerator {
}; };
}; };
/// CallIntrinsicHelper will call the intrinsic helper function, creating it /// CallBuiltinHelper will call the builtin helper function, creating it
/// if it hasn't been built already. If the intrinsic needs to be built then /// if it hasn't been built already. If the builtin needs to be built then
/// CallIntrinsicHelper will generate the function signature and will call /// CallBuiltinHelper will generate the function signature and will call
/// `build` to emit the body of the function. /// `build` to emit the body of the function.
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @param build a function with the signature: /// @param build a function with the signature:
/// `bool(TextBuffer* buffer, const std::vector<std::string>& params)` /// `bool(TextBuffer* buffer, const std::vector<std::string>& params)`
/// Where: /// Where:
@ -527,16 +527,16 @@ class GeneratorImpl : public TextGenerator {
/// `params` is the name of all the generated function parameters /// `params` is the name of all the generated function parameters
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
template <typename F> template <typename F>
bool CallIntrinsicHelper(std::ostream& out, bool CallBuiltinHelper(std::ostream& out,
const ast::CallExpression* call, const ast::CallExpression* call,
const sem::Intrinsic* intrinsic, const sem::Builtin* builtin,
F&& build); F&& build);
TextBuffer helpers_; // Helper functions emitted at the top of the output TextBuffer helpers_; // Helper functions emitted at the top of the output
std::function<bool()> emit_continuing_; std::function<bool()> emit_continuing_;
std::unordered_map<DMAIntrinsic, std::string, DMAIntrinsic::Hasher> std::unordered_map<DMAIntrinsic, std::string, DMAIntrinsic::Hasher>
dma_intrinsics_; dma_intrinsics_;
std::unordered_map<const sem::Intrinsic*, std::string> intrinsics_; std::unordered_map<const sem::Builtin*, std::string> builtins_;
std::unordered_map<const sem::Struct*, std::string> structure_builders_; std::unordered_map<const sem::Struct*, std::string> structure_builders_;
std::unordered_map<const sem::Vector*, std::string> dynamic_vector_write_; std::unordered_map<const sem::Vector*, std::string> dynamic_vector_write_;
std::unordered_map<const sem::Matrix*, std::string> std::unordered_map<const sem::Matrix*, std::string>

View File

@ -23,11 +23,11 @@ namespace writer {
namespace hlsl { namespace hlsl {
namespace { namespace {
using IntrinsicType = sem::IntrinsicType; using BuiltinType = sem::BuiltinType;
using ::testing::HasSubstr; using ::testing::HasSubstr;
using HlslGeneratorImplTest_Intrinsic = TestHelper; using HlslGeneratorImplTest_Builtin = TestHelper;
enum class ParamType { enum class ParamType {
kF32, kF32,
@ -35,12 +35,12 @@ enum class ParamType {
kBool, kBool,
}; };
struct IntrinsicData { struct BuiltinData {
IntrinsicType intrinsic; BuiltinType builtin;
ParamType type; ParamType type;
const char* hlsl_name; const char* hlsl_name;
}; };
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) { inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
out << data.hlsl_name; out << data.hlsl_name;
switch (data.type) { switch (data.type) {
case ParamType::kF32: case ParamType::kF32:
@ -57,104 +57,104 @@ inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
return out; return out;
} }
const ast::CallExpression* GenerateCall(IntrinsicType intrinsic, const ast::CallExpression* GenerateCall(BuiltinType builtin,
ParamType type, ParamType type,
ProgramBuilder* builder) { ProgramBuilder* builder) {
std::string name; std::string name;
std::ostringstream str(name); std::ostringstream str(name);
str << intrinsic; str << builtin;
switch (intrinsic) { switch (builtin) {
case IntrinsicType::kAcos: case BuiltinType::kAcos:
case IntrinsicType::kAsin: case BuiltinType::kAsin:
case IntrinsicType::kAtan: case BuiltinType::kAtan:
case IntrinsicType::kCeil: case BuiltinType::kCeil:
case IntrinsicType::kCos: case BuiltinType::kCos:
case IntrinsicType::kCosh: case BuiltinType::kCosh:
case IntrinsicType::kDpdx: case BuiltinType::kDpdx:
case IntrinsicType::kDpdxCoarse: case BuiltinType::kDpdxCoarse:
case IntrinsicType::kDpdxFine: case BuiltinType::kDpdxFine:
case IntrinsicType::kDpdy: case BuiltinType::kDpdy:
case IntrinsicType::kDpdyCoarse: case BuiltinType::kDpdyCoarse:
case IntrinsicType::kDpdyFine: case BuiltinType::kDpdyFine:
case IntrinsicType::kExp: case BuiltinType::kExp:
case IntrinsicType::kExp2: case BuiltinType::kExp2:
case IntrinsicType::kFloor: case BuiltinType::kFloor:
case IntrinsicType::kFract: case BuiltinType::kFract:
case IntrinsicType::kFwidth: case BuiltinType::kFwidth:
case IntrinsicType::kFwidthCoarse: case BuiltinType::kFwidthCoarse:
case IntrinsicType::kFwidthFine: case BuiltinType::kFwidthFine:
case IntrinsicType::kInverseSqrt: case BuiltinType::kInverseSqrt:
case IntrinsicType::kIsFinite: case BuiltinType::kIsFinite:
case IntrinsicType::kIsInf: case BuiltinType::kIsInf:
case IntrinsicType::kIsNan: case BuiltinType::kIsNan:
case IntrinsicType::kIsNormal: case BuiltinType::kIsNormal:
case IntrinsicType::kLength: case BuiltinType::kLength:
case IntrinsicType::kLog: case BuiltinType::kLog:
case IntrinsicType::kLog2: case BuiltinType::kLog2:
case IntrinsicType::kNormalize: case BuiltinType::kNormalize:
case IntrinsicType::kRound: case BuiltinType::kRound:
case IntrinsicType::kSin: case BuiltinType::kSin:
case IntrinsicType::kSinh: case BuiltinType::kSinh:
case IntrinsicType::kSqrt: case BuiltinType::kSqrt:
case IntrinsicType::kTan: case BuiltinType::kTan:
case IntrinsicType::kTanh: case BuiltinType::kTanh:
case IntrinsicType::kTrunc: case BuiltinType::kTrunc:
case IntrinsicType::kSign: case BuiltinType::kSign:
return builder->Call(str.str(), "f2"); return builder->Call(str.str(), "f2");
case IntrinsicType::kLdexp: case BuiltinType::kLdexp:
return builder->Call(str.str(), "f2", "i2"); return builder->Call(str.str(), "f2", "i2");
case IntrinsicType::kAtan2: case BuiltinType::kAtan2:
case IntrinsicType::kDot: case BuiltinType::kDot:
case IntrinsicType::kDistance: case BuiltinType::kDistance:
case IntrinsicType::kPow: case BuiltinType::kPow:
case IntrinsicType::kReflect: case BuiltinType::kReflect:
case IntrinsicType::kStep: case BuiltinType::kStep:
return builder->Call(str.str(), "f2", "f2"); return builder->Call(str.str(), "f2", "f2");
case IntrinsicType::kCross: case BuiltinType::kCross:
return builder->Call(str.str(), "f3", "f3"); return builder->Call(str.str(), "f3", "f3");
case IntrinsicType::kFma: case BuiltinType::kFma:
case IntrinsicType::kMix: case BuiltinType::kMix:
case IntrinsicType::kFaceForward: case BuiltinType::kFaceForward:
case IntrinsicType::kSmoothStep: case BuiltinType::kSmoothStep:
return builder->Call(str.str(), "f2", "f2", "f2"); return builder->Call(str.str(), "f2", "f2", "f2");
case IntrinsicType::kAll: case BuiltinType::kAll:
case IntrinsicType::kAny: case BuiltinType::kAny:
return builder->Call(str.str(), "b2"); return builder->Call(str.str(), "b2");
case IntrinsicType::kAbs: case BuiltinType::kAbs:
if (type == ParamType::kF32) { if (type == ParamType::kF32) {
return builder->Call(str.str(), "f2"); return builder->Call(str.str(), "f2");
} else { } else {
return builder->Call(str.str(), "u2"); return builder->Call(str.str(), "u2");
} }
case IntrinsicType::kCountOneBits: case BuiltinType::kCountOneBits:
case IntrinsicType::kReverseBits: case BuiltinType::kReverseBits:
return builder->Call(str.str(), "u2"); return builder->Call(str.str(), "u2");
case IntrinsicType::kMax: case BuiltinType::kMax:
case IntrinsicType::kMin: case BuiltinType::kMin:
if (type == ParamType::kF32) { if (type == ParamType::kF32) {
return builder->Call(str.str(), "f2", "f2"); return builder->Call(str.str(), "f2", "f2");
} else { } else {
return builder->Call(str.str(), "u2", "u2"); return builder->Call(str.str(), "u2", "u2");
} }
case IntrinsicType::kClamp: case BuiltinType::kClamp:
if (type == ParamType::kF32) { if (type == ParamType::kF32) {
return builder->Call(str.str(), "f2", "f2", "f2"); return builder->Call(str.str(), "f2", "f2", "f2");
} else { } else {
return builder->Call(str.str(), "u2", "u2", "u2"); return builder->Call(str.str(), "u2", "u2", "u2");
} }
case IntrinsicType::kSelect: case BuiltinType::kSelect:
return builder->Call(str.str(), "f2", "f2", "b2"); return builder->Call(str.str(), "f2", "f2", "b2");
case IntrinsicType::kDeterminant: case BuiltinType::kDeterminant:
return builder->Call(str.str(), "m2x2"); return builder->Call(str.str(), "m2x2");
case IntrinsicType::kTranspose: case BuiltinType::kTranspose:
return builder->Call(str.str(), "m3x2"); return builder->Call(str.str(), "m3x2");
default: default:
break; break;
} }
return nullptr; return nullptr;
} }
using HlslIntrinsicTest = TestParamHelper<IntrinsicData>; using HlslBuiltinTest = TestParamHelper<BuiltinData>;
TEST_P(HlslIntrinsicTest, Emit) { TEST_P(HlslBuiltinTest, Emit) {
auto param = GetParam(); auto param = GetParam();
Global("f2", ty.vec2<f32>(), ast::StorageClass::kPrivate); Global("f2", ty.vec2<f32>(), ast::StorageClass::kPrivate);
@ -165,8 +165,8 @@ TEST_P(HlslIntrinsicTest, Emit) {
Global("m2x2", ty.mat2x2<f32>(), ast::StorageClass::kPrivate); Global("m2x2", ty.mat2x2<f32>(), ast::StorageClass::kPrivate);
Global("m3x2", ty.mat3x2<f32>(), ast::StorageClass::kPrivate); Global("m3x2", ty.mat3x2<f32>(), ast::StorageClass::kPrivate);
auto* call = GenerateCall(param.intrinsic, param.type, this); auto* call = GenerateCall(param.builtin, param.type, this);
ASSERT_NE(nullptr, call) << "Unhandled intrinsic"; ASSERT_NE(nullptr, call) << "Unhandled builtin";
Func("func", {}, ty.void_(), {CallStmt(call)}, Func("func", {}, ty.void_(), {CallStmt(call)},
{create<ast::StageAttribute>(ast::PipelineStage::kFragment)}); {create<ast::StageAttribute>(ast::PipelineStage::kFragment)});
@ -176,89 +176,82 @@ TEST_P(HlslIntrinsicTest, Emit) {
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* target = sem->Target(); auto* target = sem->Target();
ASSERT_NE(target, nullptr); ASSERT_NE(target, nullptr);
auto* intrinsic = target->As<sem::Intrinsic>(); auto* builtin = target->As<sem::Builtin>();
ASSERT_NE(intrinsic, nullptr); ASSERT_NE(builtin, nullptr);
EXPECT_EQ(gen.generate_builtin_name(intrinsic), param.hlsl_name); EXPECT_EQ(gen.generate_builtin_name(builtin), param.hlsl_name);
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
HlslGeneratorImplTest_Intrinsic, HlslGeneratorImplTest_Builtin,
HlslIntrinsicTest, HlslBuiltinTest,
testing::Values( testing::Values(
IntrinsicData{IntrinsicType::kAbs, ParamType::kF32, "abs"}, BuiltinData{BuiltinType::kAbs, ParamType::kF32, "abs"},
IntrinsicData{IntrinsicType::kAbs, ParamType::kU32, "abs"}, BuiltinData{BuiltinType::kAbs, ParamType::kU32, "abs"},
IntrinsicData{IntrinsicType::kAcos, ParamType::kF32, "acos"}, BuiltinData{BuiltinType::kAcos, ParamType::kF32, "acos"},
IntrinsicData{IntrinsicType::kAll, ParamType::kBool, "all"}, BuiltinData{BuiltinType::kAll, ParamType::kBool, "all"},
IntrinsicData{IntrinsicType::kAny, ParamType::kBool, "any"}, BuiltinData{BuiltinType::kAny, ParamType::kBool, "any"},
IntrinsicData{IntrinsicType::kAsin, ParamType::kF32, "asin"}, BuiltinData{BuiltinType::kAsin, ParamType::kF32, "asin"},
IntrinsicData{IntrinsicType::kAtan, ParamType::kF32, "atan"}, BuiltinData{BuiltinType::kAtan, ParamType::kF32, "atan"},
IntrinsicData{IntrinsicType::kAtan2, ParamType::kF32, "atan2"}, BuiltinData{BuiltinType::kAtan2, ParamType::kF32, "atan2"},
IntrinsicData{IntrinsicType::kCeil, ParamType::kF32, "ceil"}, BuiltinData{BuiltinType::kCeil, ParamType::kF32, "ceil"},
IntrinsicData{IntrinsicType::kClamp, ParamType::kF32, "clamp"}, BuiltinData{BuiltinType::kClamp, ParamType::kF32, "clamp"},
IntrinsicData{IntrinsicType::kClamp, ParamType::kU32, "clamp"}, BuiltinData{BuiltinType::kClamp, ParamType::kU32, "clamp"},
IntrinsicData{IntrinsicType::kCos, ParamType::kF32, "cos"}, BuiltinData{BuiltinType::kCos, ParamType::kF32, "cos"},
IntrinsicData{IntrinsicType::kCosh, ParamType::kF32, "cosh"}, BuiltinData{BuiltinType::kCosh, ParamType::kF32, "cosh"},
IntrinsicData{IntrinsicType::kCountOneBits, ParamType::kU32, BuiltinData{BuiltinType::kCountOneBits, ParamType::kU32, "countbits"},
"countbits"}, BuiltinData{BuiltinType::kCross, ParamType::kF32, "cross"},
IntrinsicData{IntrinsicType::kCross, ParamType::kF32, "cross"}, BuiltinData{BuiltinType::kDeterminant, ParamType::kF32, "determinant"},
IntrinsicData{IntrinsicType::kDeterminant, ParamType::kF32, BuiltinData{BuiltinType::kDistance, ParamType::kF32, "distance"},
"determinant"}, BuiltinData{BuiltinType::kDot, ParamType::kF32, "dot"},
IntrinsicData{IntrinsicType::kDistance, ParamType::kF32, "distance"}, BuiltinData{BuiltinType::kDpdx, ParamType::kF32, "ddx"},
IntrinsicData{IntrinsicType::kDot, ParamType::kF32, "dot"}, BuiltinData{BuiltinType::kDpdxCoarse, ParamType::kF32, "ddx_coarse"},
IntrinsicData{IntrinsicType::kDpdx, ParamType::kF32, "ddx"}, BuiltinData{BuiltinType::kDpdxFine, ParamType::kF32, "ddx_fine"},
IntrinsicData{IntrinsicType::kDpdxCoarse, ParamType::kF32, BuiltinData{BuiltinType::kDpdy, ParamType::kF32, "ddy"},
"ddx_coarse"}, BuiltinData{BuiltinType::kDpdyCoarse, ParamType::kF32, "ddy_coarse"},
IntrinsicData{IntrinsicType::kDpdxFine, ParamType::kF32, "ddx_fine"}, BuiltinData{BuiltinType::kDpdyFine, ParamType::kF32, "ddy_fine"},
IntrinsicData{IntrinsicType::kDpdy, ParamType::kF32, "ddy"}, BuiltinData{BuiltinType::kExp, ParamType::kF32, "exp"},
IntrinsicData{IntrinsicType::kDpdyCoarse, ParamType::kF32, BuiltinData{BuiltinType::kExp2, ParamType::kF32, "exp2"},
"ddy_coarse"}, BuiltinData{BuiltinType::kFaceForward, ParamType::kF32, "faceforward"},
IntrinsicData{IntrinsicType::kDpdyFine, ParamType::kF32, "ddy_fine"}, BuiltinData{BuiltinType::kFloor, ParamType::kF32, "floor"},
IntrinsicData{IntrinsicType::kExp, ParamType::kF32, "exp"}, BuiltinData{BuiltinType::kFma, ParamType::kF32, "mad"},
IntrinsicData{IntrinsicType::kExp2, ParamType::kF32, "exp2"}, BuiltinData{BuiltinType::kFract, ParamType::kF32, "frac"},
IntrinsicData{IntrinsicType::kFaceForward, ParamType::kF32, BuiltinData{BuiltinType::kFwidth, ParamType::kF32, "fwidth"},
"faceforward"}, BuiltinData{BuiltinType::kFwidthCoarse, ParamType::kF32, "fwidth"},
IntrinsicData{IntrinsicType::kFloor, ParamType::kF32, "floor"}, BuiltinData{BuiltinType::kFwidthFine, ParamType::kF32, "fwidth"},
IntrinsicData{IntrinsicType::kFma, ParamType::kF32, "mad"}, BuiltinData{BuiltinType::kInverseSqrt, ParamType::kF32, "rsqrt"},
IntrinsicData{IntrinsicType::kFract, ParamType::kF32, "frac"}, BuiltinData{BuiltinType::kIsFinite, ParamType::kF32, "isfinite"},
IntrinsicData{IntrinsicType::kFwidth, ParamType::kF32, "fwidth"}, BuiltinData{BuiltinType::kIsInf, ParamType::kF32, "isinf"},
IntrinsicData{IntrinsicType::kFwidthCoarse, ParamType::kF32, "fwidth"}, BuiltinData{BuiltinType::kIsNan, ParamType::kF32, "isnan"},
IntrinsicData{IntrinsicType::kFwidthFine, ParamType::kF32, "fwidth"}, BuiltinData{BuiltinType::kLdexp, ParamType::kF32, "ldexp"},
IntrinsicData{IntrinsicType::kInverseSqrt, ParamType::kF32, "rsqrt"}, BuiltinData{BuiltinType::kLength, ParamType::kF32, "length"},
IntrinsicData{IntrinsicType::kIsFinite, ParamType::kF32, "isfinite"}, BuiltinData{BuiltinType::kLog, ParamType::kF32, "log"},
IntrinsicData{IntrinsicType::kIsInf, ParamType::kF32, "isinf"}, BuiltinData{BuiltinType::kLog2, ParamType::kF32, "log2"},
IntrinsicData{IntrinsicType::kIsNan, ParamType::kF32, "isnan"}, BuiltinData{BuiltinType::kMax, ParamType::kF32, "max"},
IntrinsicData{IntrinsicType::kLdexp, ParamType::kF32, "ldexp"}, BuiltinData{BuiltinType::kMax, ParamType::kU32, "max"},
IntrinsicData{IntrinsicType::kLength, ParamType::kF32, "length"}, BuiltinData{BuiltinType::kMin, ParamType::kF32, "min"},
IntrinsicData{IntrinsicType::kLog, ParamType::kF32, "log"}, BuiltinData{BuiltinType::kMin, ParamType::kU32, "min"},
IntrinsicData{IntrinsicType::kLog2, ParamType::kF32, "log2"}, BuiltinData{BuiltinType::kMix, ParamType::kF32, "lerp"},
IntrinsicData{IntrinsicType::kMax, ParamType::kF32, "max"}, BuiltinData{BuiltinType::kNormalize, ParamType::kF32, "normalize"},
IntrinsicData{IntrinsicType::kMax, ParamType::kU32, "max"}, BuiltinData{BuiltinType::kPow, ParamType::kF32, "pow"},
IntrinsicData{IntrinsicType::kMin, ParamType::kF32, "min"}, BuiltinData{BuiltinType::kReflect, ParamType::kF32, "reflect"},
IntrinsicData{IntrinsicType::kMin, ParamType::kU32, "min"}, BuiltinData{BuiltinType::kReverseBits, ParamType::kU32, "reversebits"},
IntrinsicData{IntrinsicType::kMix, ParamType::kF32, "lerp"}, BuiltinData{BuiltinType::kRound, ParamType::kU32, "round"},
IntrinsicData{IntrinsicType::kNormalize, ParamType::kF32, "normalize"}, BuiltinData{BuiltinType::kSign, ParamType::kF32, "sign"},
IntrinsicData{IntrinsicType::kPow, ParamType::kF32, "pow"}, BuiltinData{BuiltinType::kSin, ParamType::kF32, "sin"},
IntrinsicData{IntrinsicType::kReflect, ParamType::kF32, "reflect"}, BuiltinData{BuiltinType::kSinh, ParamType::kF32, "sinh"},
IntrinsicData{IntrinsicType::kReverseBits, ParamType::kU32, BuiltinData{BuiltinType::kSmoothStep, ParamType::kF32, "smoothstep"},
"reversebits"}, BuiltinData{BuiltinType::kSqrt, ParamType::kF32, "sqrt"},
IntrinsicData{IntrinsicType::kRound, ParamType::kU32, "round"}, BuiltinData{BuiltinType::kStep, ParamType::kF32, "step"},
IntrinsicData{IntrinsicType::kSign, ParamType::kF32, "sign"}, BuiltinData{BuiltinType::kTan, ParamType::kF32, "tan"},
IntrinsicData{IntrinsicType::kSin, ParamType::kF32, "sin"}, BuiltinData{BuiltinType::kTanh, ParamType::kF32, "tanh"},
IntrinsicData{IntrinsicType::kSinh, ParamType::kF32, "sinh"}, BuiltinData{BuiltinType::kTranspose, ParamType::kF32, "transpose"},
IntrinsicData{IntrinsicType::kSmoothStep, ParamType::kF32, BuiltinData{BuiltinType::kTrunc, ParamType::kF32, "trunc"}));
"smoothstep"},
IntrinsicData{IntrinsicType::kSqrt, ParamType::kF32, "sqrt"},
IntrinsicData{IntrinsicType::kStep, ParamType::kF32, "step"},
IntrinsicData{IntrinsicType::kTan, ParamType::kF32, "tan"},
IntrinsicData{IntrinsicType::kTanh, ParamType::kF32, "tanh"},
IntrinsicData{IntrinsicType::kTranspose, ParamType::kF32, "transpose"},
IntrinsicData{IntrinsicType::kTrunc, ParamType::kF32, "trunc"}));
TEST_F(HlslGeneratorImplTest_Intrinsic, DISABLED_Intrinsic_IsNormal) { TEST_F(HlslGeneratorImplTest_Builtin, DISABLED_Builtin_IsNormal) {
FAIL(); FAIL();
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Intrinsic_Call) { TEST_F(HlslGeneratorImplTest_Builtin, Builtin_Call) {
auto* call = Call("dot", "param1", "param2"); auto* call = Call("dot", "param1", "param2");
Global("param1", ty.vec3<f32>(), ast::StorageClass::kPrivate); Global("param1", ty.vec3<f32>(), ast::StorageClass::kPrivate);
@ -274,7 +267,7 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Intrinsic_Call) {
EXPECT_EQ(out.str(), "dot(param1, param2)"); EXPECT_EQ(out.str(), "dot(param1, param2)");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Scalar) { TEST_F(HlslGeneratorImplTest_Builtin, Select_Scalar) {
auto* call = Call("select", 1.0f, 2.0f, true); auto* call = Call("select", 1.0f, 2.0f, true);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -285,7 +278,7 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Scalar) {
EXPECT_EQ(out.str(), "(true ? 2.0f : 1.0f)"); EXPECT_EQ(out.str(), "(true ? 2.0f : 1.0f)");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Vector) { TEST_F(HlslGeneratorImplTest_Builtin, Select_Vector) {
auto* call = auto* call =
Call("select", vec2<i32>(1, 2), vec2<i32>(3, 4), vec2<bool>(true, false)); Call("select", vec2<i32>(1, 2), vec2<i32>(3, 4), vec2<bool>(true, false));
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -297,7 +290,7 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Vector) {
EXPECT_EQ(out.str(), "(bool2(true, false) ? int2(3, 4) : int2(1, 2))"); EXPECT_EQ(out.str(), "(bool2(true, false) ? int2(3, 4) : int2(1, 2))");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Modf_Scalar) { TEST_F(HlslGeneratorImplTest_Builtin, Modf_Scalar) {
auto* call = Call("modf", 1.0f); auto* call = Call("modf", 1.0f);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -323,7 +316,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Modf_Vector) { TEST_F(HlslGeneratorImplTest_Builtin, Modf_Vector) {
auto* call = Call("modf", vec3<f32>()); auto* call = Call("modf", vec3<f32>());
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -349,7 +342,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Scalar_i32) { TEST_F(HlslGeneratorImplTest_Builtin, Frexp_Scalar_i32) {
auto* call = Call("frexp", 1.0f); auto* call = Call("frexp", 1.0f);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -375,7 +368,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Vector_i32) { TEST_F(HlslGeneratorImplTest_Builtin, Frexp_Vector_i32) {
auto* call = Call("frexp", vec3<f32>()); auto* call = Call("frexp", vec3<f32>());
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -401,7 +394,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, IsNormal_Scalar) { TEST_F(HlslGeneratorImplTest_Builtin, IsNormal_Scalar) {
auto* val = Var("val", ty.f32()); auto* val = Var("val", ty.f32());
auto* call = Call("isNormal", val); auto* call = Call("isNormal", val);
WrapInFunction(val, call); WrapInFunction(val, call);
@ -424,7 +417,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, IsNormal_Vector) { TEST_F(HlslGeneratorImplTest_Builtin, IsNormal_Vector) {
auto* val = Var("val", ty.vec3<f32>()); auto* val = Var("val", ty.vec3<f32>());
auto* call = Call("isNormal", val); auto* call = Call("isNormal", val);
WrapInFunction(val, call); WrapInFunction(val, call);
@ -447,7 +440,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Degrees_Scalar) { TEST_F(HlslGeneratorImplTest_Builtin, Degrees_Scalar) {
auto* val = Var("val", ty.f32()); auto* val = Var("val", ty.f32());
auto* call = Call("degrees", val); auto* call = Call("degrees", val);
WrapInFunction(val, call); WrapInFunction(val, call);
@ -468,7 +461,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Degrees_Vector) { TEST_F(HlslGeneratorImplTest_Builtin, Degrees_Vector) {
auto* val = Var("val", ty.vec3<f32>()); auto* val = Var("val", ty.vec3<f32>());
auto* call = Call("degrees", val); auto* call = Call("degrees", val);
WrapInFunction(val, call); WrapInFunction(val, call);
@ -489,7 +482,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Radians_Scalar) { TEST_F(HlslGeneratorImplTest_Builtin, Radians_Scalar) {
auto* val = Var("val", ty.f32()); auto* val = Var("val", ty.f32());
auto* call = Call("radians", val); auto* call = Call("radians", val);
WrapInFunction(val, call); WrapInFunction(val, call);
@ -510,7 +503,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Radians_Vector) { TEST_F(HlslGeneratorImplTest_Builtin, Radians_Vector) {
auto* val = Var("val", ty.vec3<f32>()); auto* val = Var("val", ty.vec3<f32>());
auto* call = Call("radians", val); auto* call = Call("radians", val);
WrapInFunction(val, call); WrapInFunction(val, call);
@ -531,7 +524,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Pack4x8Snorm) { TEST_F(HlslGeneratorImplTest_Builtin, Pack4x8Snorm) {
auto* call = Call("pack4x8snorm", "p1"); auto* call = Call("pack4x8snorm", "p1");
Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate); Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -553,7 +546,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Pack4x8Unorm) { TEST_F(HlslGeneratorImplTest_Builtin, Pack4x8Unorm) {
auto* call = Call("pack4x8unorm", "p1"); auto* call = Call("pack4x8unorm", "p1");
Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate); Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -575,7 +568,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Snorm) { TEST_F(HlslGeneratorImplTest_Builtin, Pack2x16Snorm) {
auto* call = Call("pack2x16snorm", "p1"); auto* call = Call("pack2x16snorm", "p1");
Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate); Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -597,7 +590,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Unorm) { TEST_F(HlslGeneratorImplTest_Builtin, Pack2x16Unorm) {
auto* call = Call("pack2x16unorm", "p1"); auto* call = Call("pack2x16unorm", "p1");
Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate); Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -619,7 +612,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Float) { TEST_F(HlslGeneratorImplTest_Builtin, Pack2x16Float) {
auto* call = Call("pack2x16float", "p1"); auto* call = Call("pack2x16float", "p1");
Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate); Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -641,7 +634,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack4x8Snorm) { TEST_F(HlslGeneratorImplTest_Builtin, Unpack4x8Snorm) {
auto* call = Call("unpack4x8snorm", "p1"); auto* call = Call("unpack4x8snorm", "p1");
Global("p1", ty.u32(), ast::StorageClass::kPrivate); Global("p1", ty.u32(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -664,7 +657,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack4x8Unorm) { TEST_F(HlslGeneratorImplTest_Builtin, Unpack4x8Unorm) {
auto* call = Call("unpack4x8unorm", "p1"); auto* call = Call("unpack4x8unorm", "p1");
Global("p1", ty.u32(), ast::StorageClass::kPrivate); Global("p1", ty.u32(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -687,7 +680,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Snorm) { TEST_F(HlslGeneratorImplTest_Builtin, Unpack2x16Snorm) {
auto* call = Call("unpack2x16snorm", "p1"); auto* call = Call("unpack2x16snorm", "p1");
Global("p1", ty.u32(), ast::StorageClass::kPrivate); Global("p1", ty.u32(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -710,7 +703,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Unorm) { TEST_F(HlslGeneratorImplTest_Builtin, Unpack2x16Unorm) {
auto* call = Call("unpack2x16unorm", "p1"); auto* call = Call("unpack2x16unorm", "p1");
Global("p1", ty.u32(), ast::StorageClass::kPrivate); Global("p1", ty.u32(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -733,7 +726,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Float) { TEST_F(HlslGeneratorImplTest_Builtin, Unpack2x16Float) {
auto* call = Call("unpack2x16float", "p1"); auto* call = Call("unpack2x16float", "p1");
Global("p1", ty.u32(), ast::StorageClass::kPrivate); Global("p1", ty.u32(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call)); WrapInFunction(CallStmt(call));
@ -755,7 +748,7 @@ void test_function() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, StorageBarrier) { TEST_F(HlslGeneratorImplTest_Builtin, StorageBarrier) {
Func("main", {}, ty.void_(), {CallStmt(Call("storageBarrier"))}, Func("main", {}, ty.void_(), {CallStmt(Call("storageBarrier"))},
{ {
Stage(ast::PipelineStage::kCompute), Stage(ast::PipelineStage::kCompute),
@ -773,7 +766,7 @@ void main() {
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Intrinsic, WorkgroupBarrier) { TEST_F(HlslGeneratorImplTest_Builtin, WorkgroupBarrier) {
Func("main", {}, ty.void_(), {CallStmt(Call("workgroupBarrier"))}, Func("main", {}, ty.void_(), {CallStmt(Call("workgroupBarrier"))},
{ {
Stage(ast::PipelineStage::kCompute), Stage(ast::PipelineStage::kCompute),

View File

@ -13,8 +13,8 @@
// limitations under the License. // limitations under the License.
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "src/ast/builtin_texture_helper_test.h"
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/intrinsic_texture_helper_test.h"
#include "src/ast/stage_attribute.h" #include "src/ast/stage_attribute.h"
#include "src/writer/hlsl/test_helper.h" #include "src/writer/hlsl/test_helper.h"
@ -34,8 +34,8 @@ struct ExpectedResult {
}; };
ExpectedResult expected_texture_overload( ExpectedResult expected_texture_overload(
ast::intrinsic::test::ValidTextureOverload overload) { ast::builtin::test::ValidTextureOverload overload) {
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload; using ValidTextureOverload = ast::builtin::test::ValidTextureOverload;
switch (overload) { switch (overload) {
case ValidTextureOverload::kDimensions1d: case ValidTextureOverload::kDimensions1d:
case ValidTextureOverload::kDimensionsStorageWO1d: case ValidTextureOverload::kDimensionsStorageWO1d:
@ -361,10 +361,10 @@ ExpectedResult expected_texture_overload(
return "<unmatched texture overload>"; return "<unmatched texture overload>";
} // NOLINT - Ignore the length of this function } // NOLINT - Ignore the length of this function
class HlslGeneratorIntrinsicTextureTest class HlslGeneratorBuiltinTextureTest
: public TestParamHelper<ast::intrinsic::test::TextureOverloadCase> {}; : public TestParamHelper<ast::builtin::test::TextureOverloadCase> {};
TEST_P(HlslGeneratorIntrinsicTextureTest, Call) { TEST_P(HlslGeneratorBuiltinTextureTest, Call) {
auto param = GetParam(); auto param = GetParam();
param.BuildTextureVariable(this); param.BuildTextureVariable(this);
@ -386,9 +386,9 @@ TEST_P(HlslGeneratorIntrinsicTextureTest, Call) {
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
HlslGeneratorIntrinsicTextureTest, HlslGeneratorBuiltinTextureTest,
HlslGeneratorIntrinsicTextureTest, HlslGeneratorBuiltinTextureTest,
testing::ValuesIn(ast::intrinsic::test::TextureOverloadCase::ValidCases())); testing::ValuesIn(ast::builtin::test::TextureOverloadCase::ValidCases()));
} // namespace } // namespace
} // namespace hlsl } // namespace hlsl

View File

@ -542,8 +542,8 @@ bool GeneratorImpl::EmitCall(std::ostream& out,
if (auto* func = target->As<sem::Function>()) { if (auto* func = target->As<sem::Function>()) {
return EmitFunctionCall(out, call, func); return EmitFunctionCall(out, call, func);
} }
if (auto* intrinsic = target->As<sem::Intrinsic>()) { if (auto* builtin = target->As<sem::Builtin>()) {
return EmitIntrinsicCall(out, call, intrinsic); return EmitBuiltinCall(out, call, builtin);
} }
if (auto* conv = target->As<sem::TypeConversion>()) { if (auto* conv = target->As<sem::TypeConversion>()) {
return EmitTypeConversion(out, call, conv); return EmitTypeConversion(out, call, conv);
@ -579,34 +579,34 @@ bool GeneratorImpl::EmitFunctionCall(std::ostream& out,
return true; return true;
} }
bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out, bool GeneratorImpl::EmitBuiltinCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
auto* expr = call->Declaration(); auto* expr = call->Declaration();
if (intrinsic->IsAtomic()) { if (builtin->IsAtomic()) {
return EmitAtomicCall(out, expr, intrinsic); return EmitAtomicCall(out, expr, builtin);
} }
if (intrinsic->IsTexture()) { if (builtin->IsTexture()) {
return EmitTextureCall(out, call, intrinsic); return EmitTextureCall(out, call, builtin);
} }
auto name = generate_builtin_name(intrinsic); auto name = generate_builtin_name(builtin);
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kDot: case sem::BuiltinType::kDot:
return EmitDotCall(out, expr, intrinsic); return EmitDotCall(out, expr, builtin);
case sem::IntrinsicType::kModf: case sem::BuiltinType::kModf:
return EmitModfCall(out, expr, intrinsic); return EmitModfCall(out, expr, builtin);
case sem::IntrinsicType::kFrexp: case sem::BuiltinType::kFrexp:
return EmitFrexpCall(out, expr, intrinsic); return EmitFrexpCall(out, expr, builtin);
case sem::IntrinsicType::kDegrees: case sem::BuiltinType::kDegrees:
return EmitDegreesCall(out, expr, intrinsic); return EmitDegreesCall(out, expr, builtin);
case sem::IntrinsicType::kRadians: case sem::BuiltinType::kRadians:
return EmitRadiansCall(out, expr, intrinsic); return EmitRadiansCall(out, expr, builtin);
case sem::IntrinsicType::kPack2x16float: case sem::BuiltinType::kPack2x16float:
case sem::IntrinsicType::kUnpack2x16float: { case sem::BuiltinType::kUnpack2x16float: {
if (intrinsic->Type() == sem::IntrinsicType::kPack2x16float) { if (builtin->Type() == sem::BuiltinType::kPack2x16float) {
out << "as_type<uint>(half2("; out << "as_type<uint>(half2(";
} else { } else {
out << "float2(as_type<half2>("; out << "float2(as_type<half2>(";
@ -619,16 +619,16 @@ bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out,
} }
// TODO(crbug.com/tint/661): Combine sequential barriers to a single // TODO(crbug.com/tint/661): Combine sequential barriers to a single
// instruction. // instruction.
case sem::IntrinsicType::kStorageBarrier: { case sem::BuiltinType::kStorageBarrier: {
out << "threadgroup_barrier(mem_flags::mem_device)"; out << "threadgroup_barrier(mem_flags::mem_device)";
return true; return true;
} }
case sem::IntrinsicType::kWorkgroupBarrier: { case sem::BuiltinType::kWorkgroupBarrier: {
out << "threadgroup_barrier(mem_flags::mem_threadgroup)"; out << "threadgroup_barrier(mem_flags::mem_threadgroup)";
return true; return true;
} }
case sem::IntrinsicType::kLength: { case sem::BuiltinType::kLength: {
auto* sem = builder_.Sem().Get(expr->args[0]); auto* sem = builder_.Sem().Get(expr->args[0]);
if (sem->Type()->UnwrapRef()->is_scalar()) { if (sem->Type()->UnwrapRef()->is_scalar()) {
// Emulate scalar overload using fabs(x). // Emulate scalar overload using fabs(x).
@ -637,7 +637,7 @@ bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out,
break; break;
} }
case sem::IntrinsicType::kDistance: { case sem::BuiltinType::kDistance: {
auto* sem = builder_.Sem().Get(expr->args[0]); auto* sem = builder_.Sem().Get(expr->args[0]);
if (sem->Type()->UnwrapRef()->is_scalar()) { if (sem->Type()->UnwrapRef()->is_scalar()) {
// Emulate scalar overload using fabs(x - y); // Emulate scalar overload using fabs(x - y);
@ -741,7 +741,7 @@ bool GeneratorImpl::EmitTypeConstructor(std::ostream& out,
bool GeneratorImpl::EmitAtomicCall(std::ostream& out, bool GeneratorImpl::EmitAtomicCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
auto call = [&](const std::string& name, bool append_memory_order_relaxed) { auto call = [&](const std::string& name, bool append_memory_order_relaxed) {
out << name; out << name;
{ {
@ -762,38 +762,38 @@ bool GeneratorImpl::EmitAtomicCall(std::ostream& out,
return true; return true;
}; };
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kAtomicLoad: case sem::BuiltinType::kAtomicLoad:
return call("atomic_load_explicit", true); return call("atomic_load_explicit", true);
case sem::IntrinsicType::kAtomicStore: case sem::BuiltinType::kAtomicStore:
return call("atomic_store_explicit", true); return call("atomic_store_explicit", true);
case sem::IntrinsicType::kAtomicAdd: case sem::BuiltinType::kAtomicAdd:
return call("atomic_fetch_add_explicit", true); return call("atomic_fetch_add_explicit", true);
case sem::IntrinsicType::kAtomicSub: case sem::BuiltinType::kAtomicSub:
return call("atomic_fetch_sub_explicit", true); return call("atomic_fetch_sub_explicit", true);
case sem::IntrinsicType::kAtomicMax: case sem::BuiltinType::kAtomicMax:
return call("atomic_fetch_max_explicit", true); return call("atomic_fetch_max_explicit", true);
case sem::IntrinsicType::kAtomicMin: case sem::BuiltinType::kAtomicMin:
return call("atomic_fetch_min_explicit", true); return call("atomic_fetch_min_explicit", true);
case sem::IntrinsicType::kAtomicAnd: case sem::BuiltinType::kAtomicAnd:
return call("atomic_fetch_and_explicit", true); return call("atomic_fetch_and_explicit", true);
case sem::IntrinsicType::kAtomicOr: case sem::BuiltinType::kAtomicOr:
return call("atomic_fetch_or_explicit", true); return call("atomic_fetch_or_explicit", true);
case sem::IntrinsicType::kAtomicXor: case sem::BuiltinType::kAtomicXor:
return call("atomic_fetch_xor_explicit", true); return call("atomic_fetch_xor_explicit", true);
case sem::IntrinsicType::kAtomicExchange: case sem::BuiltinType::kAtomicExchange:
return call("atomic_exchange_explicit", true); return call("atomic_exchange_explicit", true);
case sem::IntrinsicType::kAtomicCompareExchangeWeak: { case sem::BuiltinType::kAtomicCompareExchangeWeak: {
auto* ptr_ty = TypeOf(expr->args[0])->UnwrapRef()->As<sem::Pointer>(); auto* ptr_ty = TypeOf(expr->args[0])->UnwrapRef()->As<sem::Pointer>();
auto sc = ptr_ty->StorageClass(); auto sc = ptr_ty->StorageClass();
@ -836,16 +836,16 @@ bool GeneratorImpl::EmitAtomicCall(std::ostream& out,
} }
TINT_UNREACHABLE(Writer, diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported atomic intrinsic: " << intrinsic->Type(); << "unsupported atomic builtin: " << builtin->Type();
return false; return false;
} }
bool GeneratorImpl::EmitTextureCall(std::ostream& out, bool GeneratorImpl::EmitTextureCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
using Usage = sem::ParameterUsage; using Usage = sem::ParameterUsage;
auto& signature = intrinsic->Signature(); auto& signature = builtin->Signature();
auto* expr = call->Declaration(); auto* expr = call->Declaration();
auto& arguments = call->Arguments(); auto& arguments = call->Arguments();
@ -883,8 +883,8 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
return true; return true;
}; };
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kTextureDimensions: { case sem::BuiltinType::kTextureDimensions: {
std::vector<const char*> dims; std::vector<const char*> dims;
switch (texture_type->dim()) { switch (texture_type->dim()) {
case ast::TextureDimension::kNone: case ast::TextureDimension::kNone:
@ -936,7 +936,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
} }
return true; return true;
} }
case sem::IntrinsicType::kTextureNumLayers: { case sem::BuiltinType::kTextureNumLayers: {
out << "int("; out << "int(";
if (!texture_expr()) { if (!texture_expr()) {
return false; return false;
@ -944,7 +944,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
out << ".get_array_size())"; out << ".get_array_size())";
return true; return true;
} }
case sem::IntrinsicType::kTextureNumLevels: { case sem::BuiltinType::kTextureNumLevels: {
out << "int("; out << "int(";
if (!texture_expr()) { if (!texture_expr()) {
return false; return false;
@ -952,7 +952,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
out << ".get_num_mip_levels())"; out << ".get_num_mip_levels())";
return true; return true;
} }
case sem::IntrinsicType::kTextureNumSamples: { case sem::BuiltinType::kTextureNumSamples: {
out << "int("; out << "int(";
if (!texture_expr()) { if (!texture_expr()) {
return false; return false;
@ -970,33 +970,33 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
bool lod_param_is_named = true; bool lod_param_is_named = true;
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kTextureSample: case sem::BuiltinType::kTextureSample:
case sem::IntrinsicType::kTextureSampleBias: case sem::BuiltinType::kTextureSampleBias:
case sem::IntrinsicType::kTextureSampleLevel: case sem::BuiltinType::kTextureSampleLevel:
case sem::IntrinsicType::kTextureSampleGrad: case sem::BuiltinType::kTextureSampleGrad:
out << ".sample("; out << ".sample(";
break; break;
case sem::IntrinsicType::kTextureSampleCompare: case sem::BuiltinType::kTextureSampleCompare:
case sem::IntrinsicType::kTextureSampleCompareLevel: case sem::BuiltinType::kTextureSampleCompareLevel:
out << ".sample_compare("; out << ".sample_compare(";
break; break;
case sem::IntrinsicType::kTextureGather: case sem::BuiltinType::kTextureGather:
out << ".gather("; out << ".gather(";
break; break;
case sem::IntrinsicType::kTextureGatherCompare: case sem::BuiltinType::kTextureGatherCompare:
out << ".gather_compare("; out << ".gather_compare(";
break; break;
case sem::IntrinsicType::kTextureLoad: case sem::BuiltinType::kTextureLoad:
out << ".read("; out << ".read(";
lod_param_is_named = false; lod_param_is_named = false;
break; break;
case sem::IntrinsicType::kTextureStore: case sem::BuiltinType::kTextureStore:
out << ".write("; out << ".write(";
break; break;
default: default:
TINT_UNREACHABLE(Writer, diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "Unhandled texture intrinsic '" << intrinsic->str() << "'"; << "Unhandled texture builtin '" << builtin->str() << "'";
return false; return false;
} }
@ -1066,7 +1066,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
out << ")"; out << ")";
} }
} }
if (intrinsic->Type() == sem::IntrinsicType::kTextureSampleCompareLevel) { if (builtin->Type() == sem::BuiltinType::kTextureSampleCompareLevel) {
maybe_write_comma(); maybe_write_comma();
out << "level(0)"; out << "level(0)";
} }
@ -1154,8 +1154,8 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
bool GeneratorImpl::EmitDotCall(std::ostream& out, bool GeneratorImpl::EmitDotCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
auto* vec_ty = intrinsic->Parameters()[0]->Type()->As<sem::Vector>(); auto* vec_ty = builtin->Parameters()[0]->Type()->As<sem::Vector>();
std::string fn = "dot"; std::string fn = "dot";
if (vec_ty->type()->is_integer_scalar()) { if (vec_ty->type()->is_integer_scalar()) {
// MSL does not have a builtin for dot() with integer vector types. // MSL does not have a builtin for dot() with integer vector types.
@ -1201,11 +1201,11 @@ bool GeneratorImpl::EmitDotCall(std::ostream& out,
bool GeneratorImpl::EmitModfCall(std::ostream& out, bool GeneratorImpl::EmitModfCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
auto* ty = intrinsic->Parameters()[0]->Type(); auto* ty = builtin->Parameters()[0]->Type();
auto in = params[0]; auto in = params[0];
std::string width; std::string width;
@ -1216,7 +1216,7 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
// Emit the builtin return type unique to this overload. This does not // Emit the builtin return type unique to this overload. This does not
// exist in the AST, so it will not be generated in Generate(). // exist in the AST, so it will not be generated in Generate().
if (!EmitStructType(&helpers_, if (!EmitStructType(&helpers_,
intrinsic->ReturnType()->As<sem::Struct>())) { builtin->ReturnType()->As<sem::Struct>())) {
return false; return false;
} }
@ -1229,11 +1229,11 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
bool GeneratorImpl::EmitFrexpCall(std::ostream& out, bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
auto* ty = intrinsic->Parameters()[0]->Type(); auto* ty = builtin->Parameters()[0]->Type();
auto in = params[0]; auto in = params[0];
std::string width; std::string width;
@ -1244,7 +1244,7 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
// Emit the builtin return type unique to this overload. This does not // Emit the builtin return type unique to this overload. This does not
// exist in the AST, so it will not be generated in Generate(). // exist in the AST, so it will not be generated in Generate().
if (!EmitStructType(&helpers_, if (!EmitStructType(&helpers_,
intrinsic->ReturnType()->As<sem::Struct>())) { builtin->ReturnType()->As<sem::Struct>())) {
return false; return false;
} }
@ -1257,9 +1257,9 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
bool GeneratorImpl::EmitDegreesCall(std::ostream& out, bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
line(b) << "return " << params[0] << " * " << std::setprecision(20) line(b) << "return " << params[0] << " * " << std::setprecision(20)
<< sem::kRadToDeg << ";"; << sem::kRadToDeg << ";";
@ -1269,9 +1269,9 @@ bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
bool GeneratorImpl::EmitRadiansCall(std::ostream& out, bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
return CallIntrinsicHelper( return CallBuiltinHelper(
out, expr, intrinsic, out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) { [&](TextBuffer* b, const std::vector<std::string>& params) {
line(b) << "return " << params[0] << " * " << std::setprecision(20) line(b) << "return " << params[0] << " * " << std::setprecision(20)
<< sem::kDegToRad << ";"; << sem::kDegToRad << ";";
@ -1279,153 +1279,152 @@ bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
}); });
} }
std::string GeneratorImpl::generate_builtin_name( std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
const sem::Intrinsic* intrinsic) {
std::string out = ""; std::string out = "";
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kAcos: case sem::BuiltinType::kAcos:
case sem::IntrinsicType::kAll: case sem::BuiltinType::kAll:
case sem::IntrinsicType::kAny: case sem::BuiltinType::kAny:
case sem::IntrinsicType::kAsin: case sem::BuiltinType::kAsin:
case sem::IntrinsicType::kAtan: case sem::BuiltinType::kAtan:
case sem::IntrinsicType::kAtan2: case sem::BuiltinType::kAtan2:
case sem::IntrinsicType::kCeil: case sem::BuiltinType::kCeil:
case sem::IntrinsicType::kCos: case sem::BuiltinType::kCos:
case sem::IntrinsicType::kCosh: case sem::BuiltinType::kCosh:
case sem::IntrinsicType::kCross: case sem::BuiltinType::kCross:
case sem::IntrinsicType::kDeterminant: case sem::BuiltinType::kDeterminant:
case sem::IntrinsicType::kDistance: case sem::BuiltinType::kDistance:
case sem::IntrinsicType::kDot: case sem::BuiltinType::kDot:
case sem::IntrinsicType::kExp: case sem::BuiltinType::kExp:
case sem::IntrinsicType::kExp2: case sem::BuiltinType::kExp2:
case sem::IntrinsicType::kFloor: case sem::BuiltinType::kFloor:
case sem::IntrinsicType::kFma: case sem::BuiltinType::kFma:
case sem::IntrinsicType::kFract: case sem::BuiltinType::kFract:
case sem::IntrinsicType::kFrexp: case sem::BuiltinType::kFrexp:
case sem::IntrinsicType::kLength: case sem::BuiltinType::kLength:
case sem::IntrinsicType::kLdexp: case sem::BuiltinType::kLdexp:
case sem::IntrinsicType::kLog: case sem::BuiltinType::kLog:
case sem::IntrinsicType::kLog2: case sem::BuiltinType::kLog2:
case sem::IntrinsicType::kMix: case sem::BuiltinType::kMix:
case sem::IntrinsicType::kModf: case sem::BuiltinType::kModf:
case sem::IntrinsicType::kNormalize: case sem::BuiltinType::kNormalize:
case sem::IntrinsicType::kPow: case sem::BuiltinType::kPow:
case sem::IntrinsicType::kReflect: case sem::BuiltinType::kReflect:
case sem::IntrinsicType::kRefract: case sem::BuiltinType::kRefract:
case sem::IntrinsicType::kSelect: case sem::BuiltinType::kSelect:
case sem::IntrinsicType::kSin: case sem::BuiltinType::kSin:
case sem::IntrinsicType::kSinh: case sem::BuiltinType::kSinh:
case sem::IntrinsicType::kSqrt: case sem::BuiltinType::kSqrt:
case sem::IntrinsicType::kStep: case sem::BuiltinType::kStep:
case sem::IntrinsicType::kTan: case sem::BuiltinType::kTan:
case sem::IntrinsicType::kTanh: case sem::BuiltinType::kTanh:
case sem::IntrinsicType::kTranspose: case sem::BuiltinType::kTranspose:
case sem::IntrinsicType::kTrunc: case sem::BuiltinType::kTrunc:
case sem::IntrinsicType::kSign: case sem::BuiltinType::kSign:
case sem::IntrinsicType::kClamp: case sem::BuiltinType::kClamp:
out += intrinsic->str(); out += builtin->str();
break; break;
case sem::IntrinsicType::kAbs: case sem::BuiltinType::kAbs:
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) { if (builtin->ReturnType()->is_float_scalar_or_vector()) {
out += "fabs"; out += "fabs";
} else { } else {
out += "abs"; out += "abs";
} }
break; break;
case sem::IntrinsicType::kCountOneBits: case sem::BuiltinType::kCountOneBits:
out += "popcount"; out += "popcount";
break; break;
case sem::IntrinsicType::kDpdx: case sem::BuiltinType::kDpdx:
case sem::IntrinsicType::kDpdxCoarse: case sem::BuiltinType::kDpdxCoarse:
case sem::IntrinsicType::kDpdxFine: case sem::BuiltinType::kDpdxFine:
out += "dfdx"; out += "dfdx";
break; break;
case sem::IntrinsicType::kDpdy: case sem::BuiltinType::kDpdy:
case sem::IntrinsicType::kDpdyCoarse: case sem::BuiltinType::kDpdyCoarse:
case sem::IntrinsicType::kDpdyFine: case sem::BuiltinType::kDpdyFine:
out += "dfdy"; out += "dfdy";
break; break;
case sem::IntrinsicType::kFwidth: case sem::BuiltinType::kFwidth:
case sem::IntrinsicType::kFwidthCoarse: case sem::BuiltinType::kFwidthCoarse:
case sem::IntrinsicType::kFwidthFine: case sem::BuiltinType::kFwidthFine:
out += "fwidth"; out += "fwidth";
break; break;
case sem::IntrinsicType::kIsFinite: case sem::BuiltinType::kIsFinite:
out += "isfinite"; out += "isfinite";
break; break;
case sem::IntrinsicType::kIsInf: case sem::BuiltinType::kIsInf:
out += "isinf"; out += "isinf";
break; break;
case sem::IntrinsicType::kIsNan: case sem::BuiltinType::kIsNan:
out += "isnan"; out += "isnan";
break; break;
case sem::IntrinsicType::kIsNormal: case sem::BuiltinType::kIsNormal:
out += "isnormal"; out += "isnormal";
break; break;
case sem::IntrinsicType::kMax: case sem::BuiltinType::kMax:
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) { if (builtin->ReturnType()->is_float_scalar_or_vector()) {
out += "fmax"; out += "fmax";
} else { } else {
out += "max"; out += "max";
} }
break; break;
case sem::IntrinsicType::kMin: case sem::BuiltinType::kMin:
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) { if (builtin->ReturnType()->is_float_scalar_or_vector()) {
out += "fmin"; out += "fmin";
} else { } else {
out += "min"; out += "min";
} }
break; break;
case sem::IntrinsicType::kFaceForward: case sem::BuiltinType::kFaceForward:
out += "faceforward"; out += "faceforward";
break; break;
case sem::IntrinsicType::kPack4x8snorm: case sem::BuiltinType::kPack4x8snorm:
out += "pack_float_to_snorm4x8"; out += "pack_float_to_snorm4x8";
break; break;
case sem::IntrinsicType::kPack4x8unorm: case sem::BuiltinType::kPack4x8unorm:
out += "pack_float_to_unorm4x8"; out += "pack_float_to_unorm4x8";
break; break;
case sem::IntrinsicType::kPack2x16snorm: case sem::BuiltinType::kPack2x16snorm:
out += "pack_float_to_snorm2x16"; out += "pack_float_to_snorm2x16";
break; break;
case sem::IntrinsicType::kPack2x16unorm: case sem::BuiltinType::kPack2x16unorm:
out += "pack_float_to_unorm2x16"; out += "pack_float_to_unorm2x16";
break; break;
case sem::IntrinsicType::kReverseBits: case sem::BuiltinType::kReverseBits:
out += "reverse_bits"; out += "reverse_bits";
break; break;
case sem::IntrinsicType::kRound: case sem::BuiltinType::kRound:
out += "rint"; out += "rint";
break; break;
case sem::IntrinsicType::kSmoothStep: case sem::BuiltinType::kSmoothStep:
out += "smoothstep"; out += "smoothstep";
break; break;
case sem::IntrinsicType::kInverseSqrt: case sem::BuiltinType::kInverseSqrt:
out += "rsqrt"; out += "rsqrt";
break; break;
case sem::IntrinsicType::kUnpack4x8snorm: case sem::BuiltinType::kUnpack4x8snorm:
out += "unpack_snorm4x8_to_float"; out += "unpack_snorm4x8_to_float";
break; break;
case sem::IntrinsicType::kUnpack4x8unorm: case sem::BuiltinType::kUnpack4x8unorm:
out += "unpack_unorm4x8_to_float"; out += "unpack_unorm4x8_to_float";
break; break;
case sem::IntrinsicType::kUnpack2x16snorm: case sem::BuiltinType::kUnpack2x16snorm:
out += "unpack_snorm2x16_to_float"; out += "unpack_snorm2x16_to_float";
break; break;
case sem::IntrinsicType::kUnpack2x16unorm: case sem::BuiltinType::kUnpack2x16unorm:
out += "unpack_unorm2x16_to_float"; out += "unpack_unorm2x16_to_float";
break; break;
case sem::IntrinsicType::kArrayLength: case sem::BuiltinType::kArrayLength:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer, diag::System::Writer,
"Unable to translate builtin: " + std::string(intrinsic->str()) + "Unable to translate builtin: " + std::string(builtin->str()) +
"\nDid you forget to pass array_length_from_uniform generator " "\nDid you forget to pass array_length_from_uniform generator "
"options?"); "options?");
return ""; return "";
default: default:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer, diag::System::Writer,
"Unknown import method: " + std::string(intrinsic->str())); "Unknown import method: " + std::string(builtin->str()));
return ""; return "";
} }
return out; return out;
@ -2871,26 +2870,26 @@ GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign(
} }
template <typename F> template <typename F>
bool GeneratorImpl::CallIntrinsicHelper(std::ostream& out, bool GeneratorImpl::CallBuiltinHelper(std::ostream& out,
const ast::CallExpression* call, const ast::CallExpression* call,
const sem::Intrinsic* intrinsic, const sem::Builtin* builtin,
F&& build) { F&& build) {
// Generate the helper function if it hasn't been created already // Generate the helper function if it hasn't been created already
auto fn = utils::GetOrCreate(intrinsics_, intrinsic, [&]() -> std::string { auto fn = utils::GetOrCreate(builtins_, builtin, [&]() -> std::string {
TextBuffer b; TextBuffer b;
TINT_DEFER(helpers_.Append(b)); TINT_DEFER(helpers_.Append(b));
auto fn_name = auto fn_name =
UniqueIdentifier(std::string("tint_") + sem::str(intrinsic->Type())); UniqueIdentifier(std::string("tint_") + sem::str(builtin->Type()));
std::vector<std::string> parameter_names; std::vector<std::string> parameter_names;
{ {
auto decl = line(&b); auto decl = line(&b);
if (!EmitTypeAndName(decl, intrinsic->ReturnType(), fn_name)) { if (!EmitTypeAndName(decl, builtin->ReturnType(), fn_name)) {
return ""; return "";
} }
{ {
ScopedParen sp(decl); ScopedParen sp(decl);
for (auto* param : intrinsic->Parameters()) { for (auto* param : builtin->Parameters()) {
if (!parameter_names.empty()) { if (!parameter_names.empty()) {
decl << ", "; decl << ", ";
} }

View File

@ -46,7 +46,7 @@ namespace tint {
// Forward declarations // Forward declarations
namespace sem { namespace sem {
class Call; class Call;
class Intrinsic; class Builtin;
class TypeConstructor; class TypeConstructor;
class TypeConversion; class TypeConversion;
} // namespace sem } // namespace sem
@ -143,14 +143,14 @@ class GeneratorImpl : public TextGenerator {
/// @param expr the call expression /// @param expr the call expression
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitCall(std::ostream& out, const ast::CallExpression* expr); bool EmitCall(std::ostream& out, const ast::CallExpression* expr);
/// Handles generating an intrinsic call expression /// Handles generating a builtin call expression
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
/// @param intrinsic the intrinsic being called /// @param builtin the builtin being called
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitIntrinsicCall(std::ostream& out, bool EmitBuiltinCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a type conversion expression /// Handles generating a type conversion expression
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
@ -179,60 +179,60 @@ class GeneratorImpl : public TextGenerator {
/// `atomicMax`, etc) /// `atomicMax`, etc)
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the atomic intrinsic /// @param builtin the semantic information for the atomic builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitAtomicCall(std::ostream& out, bool EmitAtomicCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to a texture function (`textureSample`, /// Handles generating a call to a texture function (`textureSample`,
/// `textureSampleGrad`, etc) /// `textureSampleGrad`, etc)
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
/// @param intrinsic the semantic information for the texture intrinsic /// @param builtin the semantic information for the texture builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitTextureCall(std::ostream& out, bool EmitTextureCall(std::ostream& out,
const sem::Call* call, const sem::Call* call,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `dot()` intrinsic /// Handles generating a call to the `dot()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitDotCall(std::ostream& out, bool EmitDotCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `modf()` intrinsic /// Handles generating a call to the `modf()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitModfCall(std::ostream& out, bool EmitModfCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `frexp()` intrinsic /// Handles generating a call to the `frexp()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitFrexpCall(std::ostream& out, bool EmitFrexpCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `degrees()` intrinsic /// Handles generating a call to the `degrees()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitDegreesCall(std::ostream& out, bool EmitDegreesCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a call to the `radians()` intrinsic /// Handles generating a call to the `radians()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitRadiansCall(std::ostream& out, bool EmitRadiansCall(std::ostream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles a case statement /// Handles a case statement
/// @param stmt the statement /// @param stmt the statement
/// @returns true if the statement was emitted successfully /// @returns true if the statement was emitted successfully
@ -368,9 +368,9 @@ class GeneratorImpl : public TextGenerator {
bool EmitZeroValue(std::ostream& out, const sem::Type* type); bool EmitZeroValue(std::ostream& out, const sem::Type* type);
/// Handles generating a builtin name /// Handles generating a builtin name
/// @param intrinsic the semantic info for the intrinsic /// @param builtin the semantic info for the builtin
/// @returns the name or "" if not valid /// @returns the name or "" if not valid
std::string generate_builtin_name(const sem::Intrinsic* intrinsic); std::string generate_builtin_name(const sem::Builtin* builtin);
/// Converts a builtin to an attribute name /// Converts a builtin to an attribute name
/// @param builtin the builtin to convert /// @param builtin the builtin to convert
@ -392,13 +392,13 @@ class GeneratorImpl : public TextGenerator {
uint32_t align; uint32_t align;
}; };
/// CallIntrinsicHelper will call the intrinsic helper function, creating it /// CallBuiltinHelper will call the builtin helper function, creating it
/// if it hasn't been built already. If the intrinsic needs to be built then /// if it hasn't been built already. If the builtin needs to be built then
/// CallIntrinsicHelper will generate the function signature and will call /// CallBuiltinHelper will generate the function signature and will call
/// `build` to emit the body of the function. /// `build` to emit the body of the function.
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
/// @param intrinsic the semantic information for the intrinsic /// @param builtin the semantic information for the builtin
/// @param build a function with the signature: /// @param build a function with the signature:
/// `bool(TextBuffer* buffer, const std::vector<std::string>& params)` /// `bool(TextBuffer* buffer, const std::vector<std::string>& params)`
/// Where: /// Where:
@ -406,10 +406,10 @@ class GeneratorImpl : public TextGenerator {
/// `params` is the name of all the generated function parameters /// `params` is the name of all the generated function parameters
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
template <typename F> template <typename F>
bool CallIntrinsicHelper(std::ostream& out, bool CallBuiltinHelper(std::ostream& out,
const ast::CallExpression* call, const ast::CallExpression* call,
const sem::Intrinsic* intrinsic, const sem::Builtin* builtin,
F&& build); F&& build);
TextBuffer helpers_; // Helper functions emitted at the top of the output TextBuffer helpers_; // Helper functions emitted at the top of the output
@ -438,7 +438,7 @@ class GeneratorImpl : public TextGenerator {
/// should be created for that index. /// should be created for that index.
std::unordered_map<std::string, std::vector<uint32_t>> workgroup_allocations_; std::unordered_map<std::string, std::vector<uint32_t>> workgroup_allocations_;
std::unordered_map<const sem::Intrinsic*, std::string> intrinsics_; std::unordered_map<const sem::Builtin*, std::string> builtins_;
std::unordered_map<const sem::Type*, std::string> unary_minus_funcs_; std::unordered_map<const sem::Type*, std::string> unary_minus_funcs_;
std::unordered_map<uint32_t, std::string> int_dot_funcs_; std::unordered_map<uint32_t, std::string> int_dot_funcs_;
}; };

View File

@ -21,7 +21,7 @@ namespace writer {
namespace msl { namespace msl {
namespace { namespace {
using IntrinsicType = sem::IntrinsicType; using BuiltinType = sem::BuiltinType;
using MslGeneratorImplTest = TestHelper; using MslGeneratorImplTest = TestHelper;
@ -31,12 +31,12 @@ enum class ParamType {
kBool, kBool,
}; };
struct IntrinsicData { struct BuiltinData {
IntrinsicType intrinsic; BuiltinType builtin;
ParamType type; ParamType type;
const char* msl_name; const char* msl_name;
}; };
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) { inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
out << data.msl_name << "<"; out << data.msl_name << "<";
switch (data.type) { switch (data.type) {
case ParamType::kF32: case ParamType::kF32:
@ -53,111 +53,111 @@ inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
return out; return out;
} }
const ast::CallExpression* GenerateCall(IntrinsicType intrinsic, const ast::CallExpression* GenerateCall(BuiltinType builtin,
ParamType type, ParamType type,
ProgramBuilder* builder) { ProgramBuilder* builder) {
std::string name; std::string name;
std::ostringstream str(name); std::ostringstream str(name);
str << intrinsic; str << builtin;
switch (intrinsic) { switch (builtin) {
case IntrinsicType::kAcos: case BuiltinType::kAcos:
case IntrinsicType::kAsin: case BuiltinType::kAsin:
case IntrinsicType::kAtan: case BuiltinType::kAtan:
case IntrinsicType::kCeil: case BuiltinType::kCeil:
case IntrinsicType::kCos: case BuiltinType::kCos:
case IntrinsicType::kCosh: case BuiltinType::kCosh:
case IntrinsicType::kDpdx: case BuiltinType::kDpdx:
case IntrinsicType::kDpdxCoarse: case BuiltinType::kDpdxCoarse:
case IntrinsicType::kDpdxFine: case BuiltinType::kDpdxFine:
case IntrinsicType::kDpdy: case BuiltinType::kDpdy:
case IntrinsicType::kDpdyCoarse: case BuiltinType::kDpdyCoarse:
case IntrinsicType::kDpdyFine: case BuiltinType::kDpdyFine:
case IntrinsicType::kExp: case BuiltinType::kExp:
case IntrinsicType::kExp2: case BuiltinType::kExp2:
case IntrinsicType::kFloor: case BuiltinType::kFloor:
case IntrinsicType::kFract: case BuiltinType::kFract:
case IntrinsicType::kFwidth: case BuiltinType::kFwidth:
case IntrinsicType::kFwidthCoarse: case BuiltinType::kFwidthCoarse:
case IntrinsicType::kFwidthFine: case BuiltinType::kFwidthFine:
case IntrinsicType::kInverseSqrt: case BuiltinType::kInverseSqrt:
case IntrinsicType::kIsFinite: case BuiltinType::kIsFinite:
case IntrinsicType::kIsInf: case BuiltinType::kIsInf:
case IntrinsicType::kIsNan: case BuiltinType::kIsNan:
case IntrinsicType::kIsNormal: case BuiltinType::kIsNormal:
case IntrinsicType::kLength: case BuiltinType::kLength:
case IntrinsicType::kLog: case BuiltinType::kLog:
case IntrinsicType::kLog2: case BuiltinType::kLog2:
case IntrinsicType::kNormalize: case BuiltinType::kNormalize:
case IntrinsicType::kRound: case BuiltinType::kRound:
case IntrinsicType::kSin: case BuiltinType::kSin:
case IntrinsicType::kSinh: case BuiltinType::kSinh:
case IntrinsicType::kSqrt: case BuiltinType::kSqrt:
case IntrinsicType::kTan: case BuiltinType::kTan:
case IntrinsicType::kTanh: case BuiltinType::kTanh:
case IntrinsicType::kTrunc: case BuiltinType::kTrunc:
case IntrinsicType::kSign: case BuiltinType::kSign:
return builder->Call(str.str(), "f2"); return builder->Call(str.str(), "f2");
case IntrinsicType::kLdexp: case BuiltinType::kLdexp:
return builder->Call(str.str(), "f2", "i2"); return builder->Call(str.str(), "f2", "i2");
case IntrinsicType::kAtan2: case BuiltinType::kAtan2:
case IntrinsicType::kDot: case BuiltinType::kDot:
case IntrinsicType::kDistance: case BuiltinType::kDistance:
case IntrinsicType::kPow: case BuiltinType::kPow:
case IntrinsicType::kReflect: case BuiltinType::kReflect:
case IntrinsicType::kStep: case BuiltinType::kStep:
return builder->Call(str.str(), "f2", "f2"); return builder->Call(str.str(), "f2", "f2");
case IntrinsicType::kStorageBarrier: case BuiltinType::kStorageBarrier:
return builder->Call(str.str()); return builder->Call(str.str());
case IntrinsicType::kCross: case BuiltinType::kCross:
return builder->Call(str.str(), "f3", "f3"); return builder->Call(str.str(), "f3", "f3");
case IntrinsicType::kFma: case BuiltinType::kFma:
case IntrinsicType::kMix: case BuiltinType::kMix:
case IntrinsicType::kFaceForward: case BuiltinType::kFaceForward:
case IntrinsicType::kSmoothStep: case BuiltinType::kSmoothStep:
return builder->Call(str.str(), "f2", "f2", "f2"); return builder->Call(str.str(), "f2", "f2", "f2");
case IntrinsicType::kAll: case BuiltinType::kAll:
case IntrinsicType::kAny: case BuiltinType::kAny:
return builder->Call(str.str(), "b2"); return builder->Call(str.str(), "b2");
case IntrinsicType::kAbs: case BuiltinType::kAbs:
if (type == ParamType::kF32) { if (type == ParamType::kF32) {
return builder->Call(str.str(), "f2"); return builder->Call(str.str(), "f2");
} else { } else {
return builder->Call(str.str(), "u2"); return builder->Call(str.str(), "u2");
} }
case IntrinsicType::kCountOneBits: case BuiltinType::kCountOneBits:
case IntrinsicType::kReverseBits: case BuiltinType::kReverseBits:
return builder->Call(str.str(), "u2"); return builder->Call(str.str(), "u2");
case IntrinsicType::kMax: case BuiltinType::kMax:
case IntrinsicType::kMin: case BuiltinType::kMin:
if (type == ParamType::kF32) { if (type == ParamType::kF32) {
return builder->Call(str.str(), "f2", "f2"); return builder->Call(str.str(), "f2", "f2");
} else { } else {
return builder->Call(str.str(), "u2", "u2"); return builder->Call(str.str(), "u2", "u2");
} }
case IntrinsicType::kClamp: case BuiltinType::kClamp:
if (type == ParamType::kF32) { if (type == ParamType::kF32) {
return builder->Call(str.str(), "f2", "f2", "f2"); return builder->Call(str.str(), "f2", "f2", "f2");
} else { } else {
return builder->Call(str.str(), "u2", "u2", "u2"); return builder->Call(str.str(), "u2", "u2", "u2");
} }
case IntrinsicType::kSelect: case BuiltinType::kSelect:
return builder->Call(str.str(), "f2", "f2", "b2"); return builder->Call(str.str(), "f2", "f2", "b2");
case IntrinsicType::kDeterminant: case BuiltinType::kDeterminant:
return builder->Call(str.str(), "m2x2"); return builder->Call(str.str(), "m2x2");
case IntrinsicType::kPack2x16snorm: case BuiltinType::kPack2x16snorm:
case IntrinsicType::kPack2x16unorm: case BuiltinType::kPack2x16unorm:
return builder->Call(str.str(), "f2"); return builder->Call(str.str(), "f2");
case IntrinsicType::kPack4x8snorm: case BuiltinType::kPack4x8snorm:
case IntrinsicType::kPack4x8unorm: case BuiltinType::kPack4x8unorm:
return builder->Call(str.str(), "f4"); return builder->Call(str.str(), "f4");
case IntrinsicType::kUnpack4x8snorm: case BuiltinType::kUnpack4x8snorm:
case IntrinsicType::kUnpack4x8unorm: case BuiltinType::kUnpack4x8unorm:
case IntrinsicType::kUnpack2x16snorm: case BuiltinType::kUnpack2x16snorm:
case IntrinsicType::kUnpack2x16unorm: case BuiltinType::kUnpack2x16unorm:
return builder->Call(str.str(), "u1"); return builder->Call(str.str(), "u1");
case IntrinsicType::kWorkgroupBarrier: case BuiltinType::kWorkgroupBarrier:
return builder->Call(str.str()); return builder->Call(str.str());
case IntrinsicType::kTranspose: case BuiltinType::kTranspose:
return builder->Call(str.str(), "m3x2"); return builder->Call(str.str(), "m3x2");
default: default:
break; break;
@ -165,8 +165,8 @@ const ast::CallExpression* GenerateCall(IntrinsicType intrinsic,
return nullptr; return nullptr;
} }
using MslIntrinsicTest = TestParamHelper<IntrinsicData>; using MslBuiltinTest = TestParamHelper<BuiltinData>;
TEST_P(MslIntrinsicTest, Emit) { TEST_P(MslBuiltinTest, Emit) {
auto param = GetParam(); auto param = GetParam();
Global("f2", ty.vec2<f32>(), ast::StorageClass::kPrivate); Global("f2", ty.vec2<f32>(), ast::StorageClass::kPrivate);
@ -179,8 +179,8 @@ TEST_P(MslIntrinsicTest, Emit) {
Global("m2x2", ty.mat2x2<f32>(), ast::StorageClass::kPrivate); Global("m2x2", ty.mat2x2<f32>(), ast::StorageClass::kPrivate);
Global("m3x2", ty.mat3x2<f32>(), ast::StorageClass::kPrivate); Global("m3x2", ty.mat3x2<f32>(), ast::StorageClass::kPrivate);
auto* call = GenerateCall(param.intrinsic, param.type, this); auto* call = GenerateCall(param.builtin, param.type, this);
ASSERT_NE(nullptr, call) << "Unhandled intrinsic"; ASSERT_NE(nullptr, call) << "Unhandled builtin";
Func("func", {}, ty.void_(), {Ignore(call)}, Func("func", {}, ty.void_(), {Ignore(call)},
{create<ast::StageAttribute>(ast::PipelineStage::kFragment)}); {create<ast::StageAttribute>(ast::PipelineStage::kFragment)});
@ -190,100 +190,95 @@ TEST_P(MslIntrinsicTest, Emit) {
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* target = sem->Target(); auto* target = sem->Target();
ASSERT_NE(target, nullptr); ASSERT_NE(target, nullptr);
auto* intrinsic = target->As<sem::Intrinsic>(); auto* builtin = target->As<sem::Builtin>();
ASSERT_NE(intrinsic, nullptr); ASSERT_NE(builtin, nullptr);
EXPECT_EQ(gen.generate_builtin_name(intrinsic), param.msl_name); EXPECT_EQ(gen.generate_builtin_name(builtin), param.msl_name);
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
MslGeneratorImplTest, MslGeneratorImplTest,
MslIntrinsicTest, MslBuiltinTest,
testing::Values( testing::Values(
IntrinsicData{IntrinsicType::kAbs, ParamType::kF32, "fabs"}, BuiltinData{BuiltinType::kAbs, ParamType::kF32, "fabs"},
IntrinsicData{IntrinsicType::kAbs, ParamType::kU32, "abs"}, BuiltinData{BuiltinType::kAbs, ParamType::kU32, "abs"},
IntrinsicData{IntrinsicType::kAcos, ParamType::kF32, "acos"}, BuiltinData{BuiltinType::kAcos, ParamType::kF32, "acos"},
IntrinsicData{IntrinsicType::kAll, ParamType::kBool, "all"}, BuiltinData{BuiltinType::kAll, ParamType::kBool, "all"},
IntrinsicData{IntrinsicType::kAny, ParamType::kBool, "any"}, BuiltinData{BuiltinType::kAny, ParamType::kBool, "any"},
IntrinsicData{IntrinsicType::kAsin, ParamType::kF32, "asin"}, BuiltinData{BuiltinType::kAsin, ParamType::kF32, "asin"},
IntrinsicData{IntrinsicType::kAtan, ParamType::kF32, "atan"}, BuiltinData{BuiltinType::kAtan, ParamType::kF32, "atan"},
IntrinsicData{IntrinsicType::kAtan2, ParamType::kF32, "atan2"}, BuiltinData{BuiltinType::kAtan2, ParamType::kF32, "atan2"},
IntrinsicData{IntrinsicType::kCeil, ParamType::kF32, "ceil"}, BuiltinData{BuiltinType::kCeil, ParamType::kF32, "ceil"},
IntrinsicData{IntrinsicType::kClamp, ParamType::kF32, "clamp"}, BuiltinData{BuiltinType::kClamp, ParamType::kF32, "clamp"},
IntrinsicData{IntrinsicType::kClamp, ParamType::kU32, "clamp"}, BuiltinData{BuiltinType::kClamp, ParamType::kU32, "clamp"},
IntrinsicData{IntrinsicType::kCos, ParamType::kF32, "cos"}, BuiltinData{BuiltinType::kCos, ParamType::kF32, "cos"},
IntrinsicData{IntrinsicType::kCosh, ParamType::kF32, "cosh"}, BuiltinData{BuiltinType::kCosh, ParamType::kF32, "cosh"},
IntrinsicData{IntrinsicType::kCountOneBits, ParamType::kU32, BuiltinData{BuiltinType::kCountOneBits, ParamType::kU32, "popcount"},
"popcount"}, BuiltinData{BuiltinType::kCross, ParamType::kF32, "cross"},
IntrinsicData{IntrinsicType::kCross, ParamType::kF32, "cross"}, BuiltinData{BuiltinType::kDeterminant, ParamType::kF32, "determinant"},
IntrinsicData{IntrinsicType::kDeterminant, ParamType::kF32, BuiltinData{BuiltinType::kDistance, ParamType::kF32, "distance"},
"determinant"}, BuiltinData{BuiltinType::kDot, ParamType::kF32, "dot"},
IntrinsicData{IntrinsicType::kDistance, ParamType::kF32, "distance"}, BuiltinData{BuiltinType::kDpdx, ParamType::kF32, "dfdx"},
IntrinsicData{IntrinsicType::kDot, ParamType::kF32, "dot"}, BuiltinData{BuiltinType::kDpdxCoarse, ParamType::kF32, "dfdx"},
IntrinsicData{IntrinsicType::kDpdx, ParamType::kF32, "dfdx"}, BuiltinData{BuiltinType::kDpdxFine, ParamType::kF32, "dfdx"},
IntrinsicData{IntrinsicType::kDpdxCoarse, ParamType::kF32, "dfdx"}, BuiltinData{BuiltinType::kDpdy, ParamType::kF32, "dfdy"},
IntrinsicData{IntrinsicType::kDpdxFine, ParamType::kF32, "dfdx"}, BuiltinData{BuiltinType::kDpdyCoarse, ParamType::kF32, "dfdy"},
IntrinsicData{IntrinsicType::kDpdy, ParamType::kF32, "dfdy"}, BuiltinData{BuiltinType::kDpdyFine, ParamType::kF32, "dfdy"},
IntrinsicData{IntrinsicType::kDpdyCoarse, ParamType::kF32, "dfdy"}, BuiltinData{BuiltinType::kExp, ParamType::kF32, "exp"},
IntrinsicData{IntrinsicType::kDpdyFine, ParamType::kF32, "dfdy"}, BuiltinData{BuiltinType::kExp2, ParamType::kF32, "exp2"},
IntrinsicData{IntrinsicType::kExp, ParamType::kF32, "exp"}, BuiltinData{BuiltinType::kFaceForward, ParamType::kF32, "faceforward"},
IntrinsicData{IntrinsicType::kExp2, ParamType::kF32, "exp2"}, BuiltinData{BuiltinType::kFloor, ParamType::kF32, "floor"},
IntrinsicData{IntrinsicType::kFaceForward, ParamType::kF32, BuiltinData{BuiltinType::kFma, ParamType::kF32, "fma"},
"faceforward"}, BuiltinData{BuiltinType::kFract, ParamType::kF32, "fract"},
IntrinsicData{IntrinsicType::kFloor, ParamType::kF32, "floor"}, BuiltinData{BuiltinType::kFwidth, ParamType::kF32, "fwidth"},
IntrinsicData{IntrinsicType::kFma, ParamType::kF32, "fma"}, BuiltinData{BuiltinType::kFwidthCoarse, ParamType::kF32, "fwidth"},
IntrinsicData{IntrinsicType::kFract, ParamType::kF32, "fract"}, BuiltinData{BuiltinType::kFwidthFine, ParamType::kF32, "fwidth"},
IntrinsicData{IntrinsicType::kFwidth, ParamType::kF32, "fwidth"}, BuiltinData{BuiltinType::kInverseSqrt, ParamType::kF32, "rsqrt"},
IntrinsicData{IntrinsicType::kFwidthCoarse, ParamType::kF32, "fwidth"}, BuiltinData{BuiltinType::kIsFinite, ParamType::kF32, "isfinite"},
IntrinsicData{IntrinsicType::kFwidthFine, ParamType::kF32, "fwidth"}, BuiltinData{BuiltinType::kIsInf, ParamType::kF32, "isinf"},
IntrinsicData{IntrinsicType::kInverseSqrt, ParamType::kF32, "rsqrt"}, BuiltinData{BuiltinType::kIsNan, ParamType::kF32, "isnan"},
IntrinsicData{IntrinsicType::kIsFinite, ParamType::kF32, "isfinite"}, BuiltinData{BuiltinType::kIsNormal, ParamType::kF32, "isnormal"},
IntrinsicData{IntrinsicType::kIsInf, ParamType::kF32, "isinf"}, BuiltinData{BuiltinType::kLdexp, ParamType::kF32, "ldexp"},
IntrinsicData{IntrinsicType::kIsNan, ParamType::kF32, "isnan"}, BuiltinData{BuiltinType::kLength, ParamType::kF32, "length"},
IntrinsicData{IntrinsicType::kIsNormal, ParamType::kF32, "isnormal"}, BuiltinData{BuiltinType::kLog, ParamType::kF32, "log"},
IntrinsicData{IntrinsicType::kLdexp, ParamType::kF32, "ldexp"}, BuiltinData{BuiltinType::kLog2, ParamType::kF32, "log2"},
IntrinsicData{IntrinsicType::kLength, ParamType::kF32, "length"}, BuiltinData{BuiltinType::kMax, ParamType::kF32, "fmax"},
IntrinsicData{IntrinsicType::kLog, ParamType::kF32, "log"}, BuiltinData{BuiltinType::kMax, ParamType::kU32, "max"},
IntrinsicData{IntrinsicType::kLog2, ParamType::kF32, "log2"}, BuiltinData{BuiltinType::kMin, ParamType::kF32, "fmin"},
IntrinsicData{IntrinsicType::kMax, ParamType::kF32, "fmax"}, BuiltinData{BuiltinType::kMin, ParamType::kU32, "min"},
IntrinsicData{IntrinsicType::kMax, ParamType::kU32, "max"}, BuiltinData{BuiltinType::kNormalize, ParamType::kF32, "normalize"},
IntrinsicData{IntrinsicType::kMin, ParamType::kF32, "fmin"}, BuiltinData{BuiltinType::kPack4x8snorm, ParamType::kF32,
IntrinsicData{IntrinsicType::kMin, ParamType::kU32, "min"}, "pack_float_to_snorm4x8"},
IntrinsicData{IntrinsicType::kNormalize, ParamType::kF32, "normalize"}, BuiltinData{BuiltinType::kPack4x8unorm, ParamType::kF32,
IntrinsicData{IntrinsicType::kPack4x8snorm, ParamType::kF32, "pack_float_to_unorm4x8"},
"pack_float_to_snorm4x8"}, BuiltinData{BuiltinType::kPack2x16snorm, ParamType::kF32,
IntrinsicData{IntrinsicType::kPack4x8unorm, ParamType::kF32, "pack_float_to_snorm2x16"},
"pack_float_to_unorm4x8"}, BuiltinData{BuiltinType::kPack2x16unorm, ParamType::kF32,
IntrinsicData{IntrinsicType::kPack2x16snorm, ParamType::kF32, "pack_float_to_unorm2x16"},
"pack_float_to_snorm2x16"}, BuiltinData{BuiltinType::kPow, ParamType::kF32, "pow"},
IntrinsicData{IntrinsicType::kPack2x16unorm, ParamType::kF32, BuiltinData{BuiltinType::kReflect, ParamType::kF32, "reflect"},
"pack_float_to_unorm2x16"}, BuiltinData{BuiltinType::kReverseBits, ParamType::kU32, "reverse_bits"},
IntrinsicData{IntrinsicType::kPow, ParamType::kF32, "pow"}, BuiltinData{BuiltinType::kRound, ParamType::kU32, "rint"},
IntrinsicData{IntrinsicType::kReflect, ParamType::kF32, "reflect"}, BuiltinData{BuiltinType::kSelect, ParamType::kF32, "select"},
IntrinsicData{IntrinsicType::kReverseBits, ParamType::kU32, BuiltinData{BuiltinType::kSign, ParamType::kF32, "sign"},
"reverse_bits"}, BuiltinData{BuiltinType::kSin, ParamType::kF32, "sin"},
IntrinsicData{IntrinsicType::kRound, ParamType::kU32, "rint"}, BuiltinData{BuiltinType::kSinh, ParamType::kF32, "sinh"},
IntrinsicData{IntrinsicType::kSelect, ParamType::kF32, "select"}, BuiltinData{BuiltinType::kSmoothStep, ParamType::kF32, "smoothstep"},
IntrinsicData{IntrinsicType::kSign, ParamType::kF32, "sign"}, BuiltinData{BuiltinType::kSqrt, ParamType::kF32, "sqrt"},
IntrinsicData{IntrinsicType::kSin, ParamType::kF32, "sin"}, BuiltinData{BuiltinType::kStep, ParamType::kF32, "step"},
IntrinsicData{IntrinsicType::kSinh, ParamType::kF32, "sinh"}, BuiltinData{BuiltinType::kTan, ParamType::kF32, "tan"},
IntrinsicData{IntrinsicType::kSmoothStep, ParamType::kF32, BuiltinData{BuiltinType::kTanh, ParamType::kF32, "tanh"},
"smoothstep"}, BuiltinData{BuiltinType::kTranspose, ParamType::kF32, "transpose"},
IntrinsicData{IntrinsicType::kSqrt, ParamType::kF32, "sqrt"}, BuiltinData{BuiltinType::kTrunc, ParamType::kF32, "trunc"},
IntrinsicData{IntrinsicType::kStep, ParamType::kF32, "step"}, BuiltinData{BuiltinType::kUnpack4x8snorm, ParamType::kU32,
IntrinsicData{IntrinsicType::kTan, ParamType::kF32, "tan"}, "unpack_snorm4x8_to_float"},
IntrinsicData{IntrinsicType::kTanh, ParamType::kF32, "tanh"}, BuiltinData{BuiltinType::kUnpack4x8unorm, ParamType::kU32,
IntrinsicData{IntrinsicType::kTranspose, ParamType::kF32, "transpose"}, "unpack_unorm4x8_to_float"},
IntrinsicData{IntrinsicType::kTrunc, ParamType::kF32, "trunc"}, BuiltinData{BuiltinType::kUnpack2x16snorm, ParamType::kU32,
IntrinsicData{IntrinsicType::kUnpack4x8snorm, ParamType::kU32, "unpack_snorm2x16_to_float"},
"unpack_snorm4x8_to_float"}, BuiltinData{BuiltinType::kUnpack2x16unorm, ParamType::kU32,
IntrinsicData{IntrinsicType::kUnpack4x8unorm, ParamType::kU32, "unpack_unorm2x16_to_float"}));
"unpack_unorm4x8_to_float"},
IntrinsicData{IntrinsicType::kUnpack2x16snorm, ParamType::kU32,
"unpack_snorm2x16_to_float"},
IntrinsicData{IntrinsicType::kUnpack2x16unorm, ParamType::kU32,
"unpack_unorm2x16_to_float"}));
TEST_F(MslGeneratorImplTest, Intrinsic_Call) { TEST_F(MslGeneratorImplTest, Builtin_Call) {
Global("param1", ty.vec2<f32>(), ast::StorageClass::kPrivate); Global("param1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
Global("param2", ty.vec2<f32>(), ast::StorageClass::kPrivate); Global("param2", ty.vec2<f32>(), ast::StorageClass::kPrivate);

View File

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/builtin_texture_helper_test.h"
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/intrinsic_texture_helper_test.h"
#include "src/writer/msl/test_helper.h" #include "src/writer/msl/test_helper.h"
namespace tint { namespace tint {
@ -22,8 +22,8 @@ namespace msl {
namespace { namespace {
std::string expected_texture_overload( std::string expected_texture_overload(
ast::intrinsic::test::ValidTextureOverload overload) { ast::builtin::test::ValidTextureOverload overload) {
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload; using ValidTextureOverload = ast::builtin::test::ValidTextureOverload;
switch (overload) { switch (overload) {
case ValidTextureOverload::kDimensions1d: case ValidTextureOverload::kDimensions1d:
case ValidTextureOverload::kDimensionsStorageWO1d: case ValidTextureOverload::kDimensionsStorageWO1d:
@ -271,10 +271,10 @@ std::string expected_texture_overload(
return "<unmatched texture overload>"; return "<unmatched texture overload>";
} // NOLINT - Ignore the length of this function } // NOLINT - Ignore the length of this function
class MslGeneratorIntrinsicTextureTest class MslGeneratorBuiltinTextureTest
: public TestParamHelper<ast::intrinsic::test::TextureOverloadCase> {}; : public TestParamHelper<ast::builtin::test::TextureOverloadCase> {};
TEST_P(MslGeneratorIntrinsicTextureTest, Call) { TEST_P(MslGeneratorBuiltinTextureTest, Call) {
auto param = GetParam(); auto param = GetParam();
param.BuildTextureVariable(this); param.BuildTextureVariable(this);
@ -295,9 +295,9 @@ TEST_P(MslGeneratorIntrinsicTextureTest, Call) {
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
MslGeneratorIntrinsicTextureTest, MslGeneratorBuiltinTextureTest,
MslGeneratorIntrinsicTextureTest, MslGeneratorBuiltinTextureTest,
testing::ValuesIn(ast::intrinsic::test::TextureOverloadCase::ValidCases())); testing::ValuesIn(ast::builtin::test::TextureOverloadCase::ValidCases()));
} // namespace } // namespace
} // namespace msl } // namespace msl

View File

@ -35,7 +35,7 @@ TEST_P(MslImportData_SingleParamTest, FloatScalar) {
auto param = GetParam(); auto param = GetParam();
auto* call = Call(param.name, 1.f); auto* call = Call(param.name, 1.f);
// The resolver will set the intrinsic data for the ident // The resolver will set the builtin data for the ident
WrapInFunction(call); WrapInFunction(call);
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -44,10 +44,10 @@ TEST_P(MslImportData_SingleParamTest, FloatScalar) {
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* target = sem->Target(); auto* target = sem->Target();
ASSERT_NE(target, nullptr); ASSERT_NE(target, nullptr);
auto* intrinsic = target->As<sem::Intrinsic>(); auto* builtin = target->As<sem::Builtin>();
ASSERT_NE(intrinsic, nullptr); ASSERT_NE(builtin, nullptr);
ASSERT_EQ(gen.generate_builtin_name(intrinsic), param.msl_name); ASSERT_EQ(gen.generate_builtin_name(builtin), param.msl_name);
} }
INSTANTIATE_TEST_SUITE_P(MslGeneratorImplTest, INSTANTIATE_TEST_SUITE_P(MslGeneratorImplTest,
MslImportData_SingleParamTest, MslImportData_SingleParamTest,

View File

@ -25,11 +25,11 @@
#include "src/ast/traverse_expressions.h" #include "src/ast/traverse_expressions.h"
#include "src/sem/array.h" #include "src/sem/array.h"
#include "src/sem/atomic_type.h" #include "src/sem/atomic_type.h"
#include "src/sem/builtin.h"
#include "src/sem/call.h" #include "src/sem/call.h"
#include "src/sem/depth_multisampled_texture_type.h" #include "src/sem/depth_multisampled_texture_type.h"
#include "src/sem/depth_texture_type.h" #include "src/sem/depth_texture_type.h"
#include "src/sem/function.h" #include "src/sem/function.h"
#include "src/sem/intrinsic.h"
#include "src/sem/member_accessor_expression.h" #include "src/sem/member_accessor_expression.h"
#include "src/sem/multisampled_texture_type.h" #include "src/sem/multisampled_texture_type.h"
#include "src/sem/reference_type.h" #include "src/sem/reference_type.h"
@ -62,7 +62,7 @@ namespace writer {
namespace spirv { namespace spirv {
namespace { namespace {
using IntrinsicType = sem::IntrinsicType; using BuiltinType = sem::BuiltinType;
const char kGLSLstd450[] = "GLSL.std.450"; const char kGLSLstd450[] = "GLSL.std.450";
@ -109,131 +109,131 @@ const sem::Matrix* GetNestedMatrixType(const sem::Type* type) {
return type->As<sem::Matrix>(); return type->As<sem::Matrix>();
} }
uint32_t intrinsic_to_glsl_method(const sem::Intrinsic* intrinsic) { uint32_t builtin_to_glsl_method(const sem::Builtin* builtin) {
switch (intrinsic->Type()) { switch (builtin->Type()) {
case IntrinsicType::kAcos: case BuiltinType::kAcos:
return GLSLstd450Acos; return GLSLstd450Acos;
case IntrinsicType::kAsin: case BuiltinType::kAsin:
return GLSLstd450Asin; return GLSLstd450Asin;
case IntrinsicType::kAtan: case BuiltinType::kAtan:
return GLSLstd450Atan; return GLSLstd450Atan;
case IntrinsicType::kAtan2: case BuiltinType::kAtan2:
return GLSLstd450Atan2; return GLSLstd450Atan2;
case IntrinsicType::kCeil: case BuiltinType::kCeil:
return GLSLstd450Ceil; return GLSLstd450Ceil;
case IntrinsicType::kClamp: case BuiltinType::kClamp:
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) { if (builtin->ReturnType()->is_float_scalar_or_vector()) {
return GLSLstd450NClamp; return GLSLstd450NClamp;
} else if (intrinsic->ReturnType()->is_unsigned_scalar_or_vector()) { } else if (builtin->ReturnType()->is_unsigned_scalar_or_vector()) {
return GLSLstd450UClamp; return GLSLstd450UClamp;
} else { } else {
return GLSLstd450SClamp; return GLSLstd450SClamp;
} }
case IntrinsicType::kCos: case BuiltinType::kCos:
return GLSLstd450Cos; return GLSLstd450Cos;
case IntrinsicType::kCosh: case BuiltinType::kCosh:
return GLSLstd450Cosh; return GLSLstd450Cosh;
case IntrinsicType::kCross: case BuiltinType::kCross:
return GLSLstd450Cross; return GLSLstd450Cross;
case IntrinsicType::kDegrees: case BuiltinType::kDegrees:
return GLSLstd450Degrees; return GLSLstd450Degrees;
case IntrinsicType::kDeterminant: case BuiltinType::kDeterminant:
return GLSLstd450Determinant; return GLSLstd450Determinant;
case IntrinsicType::kDistance: case BuiltinType::kDistance:
return GLSLstd450Distance; return GLSLstd450Distance;
case IntrinsicType::kExp: case BuiltinType::kExp:
return GLSLstd450Exp; return GLSLstd450Exp;
case IntrinsicType::kExp2: case BuiltinType::kExp2:
return GLSLstd450Exp2; return GLSLstd450Exp2;
case IntrinsicType::kFaceForward: case BuiltinType::kFaceForward:
return GLSLstd450FaceForward; return GLSLstd450FaceForward;
case IntrinsicType::kFloor: case BuiltinType::kFloor:
return GLSLstd450Floor; return GLSLstd450Floor;
case IntrinsicType::kFma: case BuiltinType::kFma:
return GLSLstd450Fma; return GLSLstd450Fma;
case IntrinsicType::kFract: case BuiltinType::kFract:
return GLSLstd450Fract; return GLSLstd450Fract;
case IntrinsicType::kFrexp: case BuiltinType::kFrexp:
return GLSLstd450FrexpStruct; return GLSLstd450FrexpStruct;
case IntrinsicType::kInverseSqrt: case BuiltinType::kInverseSqrt:
return GLSLstd450InverseSqrt; return GLSLstd450InverseSqrt;
case IntrinsicType::kLdexp: case BuiltinType::kLdexp:
return GLSLstd450Ldexp; return GLSLstd450Ldexp;
case IntrinsicType::kLength: case BuiltinType::kLength:
return GLSLstd450Length; return GLSLstd450Length;
case IntrinsicType::kLog: case BuiltinType::kLog:
return GLSLstd450Log; return GLSLstd450Log;
case IntrinsicType::kLog2: case BuiltinType::kLog2:
return GLSLstd450Log2; return GLSLstd450Log2;
case IntrinsicType::kMax: case BuiltinType::kMax:
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) { if (builtin->ReturnType()->is_float_scalar_or_vector()) {
return GLSLstd450NMax; return GLSLstd450NMax;
} else if (intrinsic->ReturnType()->is_unsigned_scalar_or_vector()) { } else if (builtin->ReturnType()->is_unsigned_scalar_or_vector()) {
return GLSLstd450UMax; return GLSLstd450UMax;
} else { } else {
return GLSLstd450SMax; return GLSLstd450SMax;
} }
case IntrinsicType::kMin: case BuiltinType::kMin:
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) { if (builtin->ReturnType()->is_float_scalar_or_vector()) {
return GLSLstd450NMin; return GLSLstd450NMin;
} else if (intrinsic->ReturnType()->is_unsigned_scalar_or_vector()) { } else if (builtin->ReturnType()->is_unsigned_scalar_or_vector()) {
return GLSLstd450UMin; return GLSLstd450UMin;
} else { } else {
return GLSLstd450SMin; return GLSLstd450SMin;
} }
case IntrinsicType::kMix: case BuiltinType::kMix:
return GLSLstd450FMix; return GLSLstd450FMix;
case IntrinsicType::kModf: case BuiltinType::kModf:
return GLSLstd450ModfStruct; return GLSLstd450ModfStruct;
case IntrinsicType::kNormalize: case BuiltinType::kNormalize:
return GLSLstd450Normalize; return GLSLstd450Normalize;
case IntrinsicType::kPack4x8snorm: case BuiltinType::kPack4x8snorm:
return GLSLstd450PackSnorm4x8; return GLSLstd450PackSnorm4x8;
case IntrinsicType::kPack4x8unorm: case BuiltinType::kPack4x8unorm:
return GLSLstd450PackUnorm4x8; return GLSLstd450PackUnorm4x8;
case IntrinsicType::kPack2x16snorm: case BuiltinType::kPack2x16snorm:
return GLSLstd450PackSnorm2x16; return GLSLstd450PackSnorm2x16;
case IntrinsicType::kPack2x16unorm: case BuiltinType::kPack2x16unorm:
return GLSLstd450PackUnorm2x16; return GLSLstd450PackUnorm2x16;
case IntrinsicType::kPack2x16float: case BuiltinType::kPack2x16float:
return GLSLstd450PackHalf2x16; return GLSLstd450PackHalf2x16;
case IntrinsicType::kPow: case BuiltinType::kPow:
return GLSLstd450Pow; return GLSLstd450Pow;
case IntrinsicType::kRadians: case BuiltinType::kRadians:
return GLSLstd450Radians; return GLSLstd450Radians;
case IntrinsicType::kReflect: case BuiltinType::kReflect:
return GLSLstd450Reflect; return GLSLstd450Reflect;
case IntrinsicType::kRefract: case BuiltinType::kRefract:
return GLSLstd450Refract; return GLSLstd450Refract;
case IntrinsicType::kRound: case BuiltinType::kRound:
return GLSLstd450RoundEven; return GLSLstd450RoundEven;
case IntrinsicType::kSign: case BuiltinType::kSign:
return GLSLstd450FSign; return GLSLstd450FSign;
case IntrinsicType::kSin: case BuiltinType::kSin:
return GLSLstd450Sin; return GLSLstd450Sin;
case IntrinsicType::kSinh: case BuiltinType::kSinh:
return GLSLstd450Sinh; return GLSLstd450Sinh;
case IntrinsicType::kSmoothStep: case BuiltinType::kSmoothStep:
return GLSLstd450SmoothStep; return GLSLstd450SmoothStep;
case IntrinsicType::kSqrt: case BuiltinType::kSqrt:
return GLSLstd450Sqrt; return GLSLstd450Sqrt;
case IntrinsicType::kStep: case BuiltinType::kStep:
return GLSLstd450Step; return GLSLstd450Step;
case IntrinsicType::kTan: case BuiltinType::kTan:
return GLSLstd450Tan; return GLSLstd450Tan;
case IntrinsicType::kTanh: case BuiltinType::kTanh:
return GLSLstd450Tanh; return GLSLstd450Tanh;
case IntrinsicType::kTrunc: case BuiltinType::kTrunc:
return GLSLstd450Trunc; return GLSLstd450Trunc;
case IntrinsicType::kUnpack4x8snorm: case BuiltinType::kUnpack4x8snorm:
return GLSLstd450UnpackSnorm4x8; return GLSLstd450UnpackSnorm4x8;
case IntrinsicType::kUnpack4x8unorm: case BuiltinType::kUnpack4x8unorm:
return GLSLstd450UnpackUnorm4x8; return GLSLstd450UnpackUnorm4x8;
case IntrinsicType::kUnpack2x16snorm: case BuiltinType::kUnpack2x16snorm:
return GLSLstd450UnpackSnorm2x16; return GLSLstd450UnpackSnorm2x16;
case IntrinsicType::kUnpack2x16unorm: case BuiltinType::kUnpack2x16unorm:
return GLSLstd450UnpackUnorm2x16; return GLSLstd450UnpackUnorm2x16;
case IntrinsicType::kUnpack2x16float: case BuiltinType::kUnpack2x16float:
return GLSLstd450UnpackHalf2x16; return GLSLstd450UnpackHalf2x16;
default: default:
break; break;
@ -2213,8 +2213,8 @@ uint32_t Builder::GenerateCallExpression(const ast::CallExpression* expr) {
if (auto* func = target->As<sem::Function>()) { if (auto* func = target->As<sem::Function>()) {
return GenerateFunctionCall(call, func); return GenerateFunctionCall(call, func);
} }
if (auto* intrinsic = target->As<sem::Intrinsic>()) { if (auto* builtin = target->As<sem::Builtin>()) {
return GenerateIntrinsicCall(call, intrinsic); return GenerateBuiltinCall(call, builtin);
} }
if (target->IsAnyOf<sem::TypeConversion, sem::TypeConstructor>()) { if (target->IsAnyOf<sem::TypeConversion, sem::TypeConstructor>()) {
return GenerateTypeConstructorOrConversion(call, nullptr); return GenerateTypeConstructorOrConversion(call, nullptr);
@ -2264,42 +2264,42 @@ uint32_t Builder::GenerateFunctionCall(const sem::Call* call,
return result_id; return result_id;
} }
uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call, uint32_t Builder::GenerateBuiltinCall(const sem::Call* call,
const sem::Intrinsic* intrinsic) { const sem::Builtin* builtin) {
auto result = result_op(); auto result = result_op();
auto result_id = result.to_i(); auto result_id = result.to_i();
auto result_type_id = GenerateTypeIfNeeded(intrinsic->ReturnType()); auto result_type_id = GenerateTypeIfNeeded(builtin->ReturnType());
if (result_type_id == 0) { if (result_type_id == 0) {
return 0; return 0;
} }
if (intrinsic->IsFineDerivative() || intrinsic->IsCoarseDerivative()) { if (builtin->IsFineDerivative() || builtin->IsCoarseDerivative()) {
push_capability(SpvCapabilityDerivativeControl); push_capability(SpvCapabilityDerivativeControl);
} }
if (intrinsic->IsImageQuery()) { if (builtin->IsImageQuery()) {
push_capability(SpvCapabilityImageQuery); push_capability(SpvCapabilityImageQuery);
} }
if (intrinsic->IsTexture()) { if (builtin->IsTexture()) {
if (!GenerateTextureIntrinsic(call, intrinsic, Operand::Int(result_type_id), if (!GenerateTextureBuiltin(call, builtin, Operand::Int(result_type_id),
result)) { result)) {
return 0; return 0;
} }
return result_id; return result_id;
} }
if (intrinsic->IsBarrier()) { if (builtin->IsBarrier()) {
if (!GenerateControlBarrierIntrinsic(intrinsic)) { if (!GenerateControlBarrierBuiltin(builtin)) {
return 0; return 0;
} }
return result_id; return result_id;
} }
if (intrinsic->IsAtomic()) { if (builtin->IsAtomic()) {
if (!GenerateAtomicIntrinsic(call, intrinsic, Operand::Int(result_type_id), if (!GenerateAtomicBuiltin(call, builtin, Operand::Int(result_type_id),
result)) { result)) {
return 0; return 0;
} }
return result_id; return result_id;
@ -2310,7 +2310,7 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
auto get_arg_as_value_id = [&](size_t i, auto get_arg_as_value_id = [&](size_t i,
bool generate_load = true) -> uint32_t { bool generate_load = true) -> uint32_t {
auto* arg = call->Arguments()[i]; auto* arg = call->Arguments()[i];
auto* param = intrinsic->Parameters()[i]; auto* param = builtin->Parameters()[i];
auto val_id = GenerateExpression(arg->Declaration()); auto val_id = GenerateExpression(arg->Declaration());
if (val_id == 0) { if (val_id == 0) {
return 0; return 0;
@ -2334,22 +2334,22 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
op = spv::Op::OpExtInst; op = spv::Op::OpExtInst;
}; };
switch (intrinsic->Type()) { switch (builtin->Type()) {
case IntrinsicType::kAny: case BuiltinType::kAny:
if (intrinsic->Parameters()[0]->Type()->Is<sem::Bool>()) { if (builtin->Parameters()[0]->Type()->Is<sem::Bool>()) {
// any(v: bool) just resolves to v. // any(v: bool) just resolves to v.
return get_arg_as_value_id(0); return get_arg_as_value_id(0);
} }
op = spv::Op::OpAny; op = spv::Op::OpAny;
break; break;
case IntrinsicType::kAll: case BuiltinType::kAll:
if (intrinsic->Parameters()[0]->Type()->Is<sem::Bool>()) { if (builtin->Parameters()[0]->Type()->Is<sem::Bool>()) {
// all(v: bool) just resolves to v. // all(v: bool) just resolves to v.
return get_arg_as_value_id(0); return get_arg_as_value_id(0);
} }
op = spv::Op::OpAll; op = spv::Op::OpAll;
break; break;
case IntrinsicType::kArrayLength: { case BuiltinType::kArrayLength: {
auto* address_of = auto* address_of =
call->Arguments()[0]->Declaration()->As<ast::UnaryOpExpression>(); call->Arguments()[0]->Declaration()->As<ast::UnaryOpExpression>();
if (!address_of || address_of->op != ast::UnaryOp::kAddressOf) { if (!address_of || address_of->op != ast::UnaryOp::kAddressOf) {
@ -2388,12 +2388,12 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
} }
return result_id; return result_id;
} }
case IntrinsicType::kCountOneBits: case BuiltinType::kCountOneBits:
op = spv::Op::OpBitCount; op = spv::Op::OpBitCount;
break; break;
case IntrinsicType::kDot: { case BuiltinType::kDot: {
op = spv::Op::OpDot; op = spv::Op::OpDot;
auto* vec_ty = intrinsic->Parameters()[0]->Type()->As<sem::Vector>(); auto* vec_ty = builtin->Parameters()[0]->Type()->As<sem::Vector>();
if (vec_ty->type()->is_integer_scalar()) { if (vec_ty->type()->is_integer_scalar()) {
// TODO(crbug.com/tint/1267): OpDot requires floating-point types, but // TODO(crbug.com/tint/1267): OpDot requires floating-point types, but
// WGSL also supports integer types. SPV_KHR_integer_dot_product adds // WGSL also supports integer types. SPV_KHR_integer_dot_product adds
@ -2433,40 +2433,40 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
} }
break; break;
} }
case IntrinsicType::kDpdx: case BuiltinType::kDpdx:
op = spv::Op::OpDPdx; op = spv::Op::OpDPdx;
break; break;
case IntrinsicType::kDpdxCoarse: case BuiltinType::kDpdxCoarse:
op = spv::Op::OpDPdxCoarse; op = spv::Op::OpDPdxCoarse;
break; break;
case IntrinsicType::kDpdxFine: case BuiltinType::kDpdxFine:
op = spv::Op::OpDPdxFine; op = spv::Op::OpDPdxFine;
break; break;
case IntrinsicType::kDpdy: case BuiltinType::kDpdy:
op = spv::Op::OpDPdy; op = spv::Op::OpDPdy;
break; break;
case IntrinsicType::kDpdyCoarse: case BuiltinType::kDpdyCoarse:
op = spv::Op::OpDPdyCoarse; op = spv::Op::OpDPdyCoarse;
break; break;
case IntrinsicType::kDpdyFine: case BuiltinType::kDpdyFine:
op = spv::Op::OpDPdyFine; op = spv::Op::OpDPdyFine;
break; break;
case IntrinsicType::kFwidth: case BuiltinType::kFwidth:
op = spv::Op::OpFwidth; op = spv::Op::OpFwidth;
break; break;
case IntrinsicType::kFwidthCoarse: case BuiltinType::kFwidthCoarse:
op = spv::Op::OpFwidthCoarse; op = spv::Op::OpFwidthCoarse;
break; break;
case IntrinsicType::kFwidthFine: case BuiltinType::kFwidthFine:
op = spv::Op::OpFwidthFine; op = spv::Op::OpFwidthFine;
break; break;
case IntrinsicType::kIsInf: case BuiltinType::kIsInf:
op = spv::Op::OpIsInf; op = spv::Op::OpIsInf;
break; break;
case IntrinsicType::kIsNan: case BuiltinType::kIsNan:
op = spv::Op::OpIsNan; op = spv::Op::OpIsNan;
break; break;
case IntrinsicType::kIsFinite: { case BuiltinType::kIsFinite: {
// Implemented as: not(IsInf or IsNan) // Implemented as: not(IsInf or IsNan)
auto val_id = get_arg_as_value_id(0); auto val_id = get_arg_as_value_id(0);
if (!val_id) { if (!val_id) {
@ -2492,7 +2492,7 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
} }
return 0; return 0;
} }
case IntrinsicType::kIsNormal: { case BuiltinType::kIsNormal: {
// A normal number is finite, non-zero, and not subnormal. // A normal number is finite, non-zero, and not subnormal.
// Its exponent is neither of the extreme possible values. // Its exponent is neither of the extreme possible values.
// Implemented as: // Implemented as:
@ -2520,7 +2520,7 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
GenerateConstantIfNeeded(ScalarConstant::U32(kMinNormalExponent)); GenerateConstantIfNeeded(ScalarConstant::U32(kMinNormalExponent));
auto max_exponent_id = auto max_exponent_id =
GenerateConstantIfNeeded(ScalarConstant::U32(kMaxNormalExponent)); GenerateConstantIfNeeded(ScalarConstant::U32(kMaxNormalExponent));
if (auto* fvec_ty = intrinsic->ReturnType()->As<sem::Vector>()) { if (auto* fvec_ty = builtin->ReturnType()->As<sem::Vector>()) {
// In the vector case, update the unsigned type to a vector type of the // In the vector case, update the unsigned type to a vector type of the
// same size, and create vector constants by replicating the scalars. // same size, and create vector constants by replicating the scalars.
// I expect backend compilers to fold these into unique constants, so // I expect backend compilers to fold these into unique constants, so
@ -2570,7 +2570,7 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
} }
return 0; return 0;
} }
case IntrinsicType::kMix: { case BuiltinType::kMix: {
auto std450 = Operand::Int(GetGLSLstd450Import()); auto std450 = Operand::Int(GetGLSLstd450Import());
auto a_id = get_arg_as_value_id(0); auto a_id = get_arg_as_value_id(0);
@ -2582,10 +2582,9 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
// If the interpolant is scalar but the objects are vectors, we need to // If the interpolant is scalar but the objects are vectors, we need to
// splat the interpolant into a vector of the same size. // splat the interpolant into a vector of the same size.
auto* result_vector_type = intrinsic->ReturnType()->As<sem::Vector>(); auto* result_vector_type = builtin->ReturnType()->As<sem::Vector>();
if (result_vector_type && if (result_vector_type && builtin->Parameters()[2]->Type()->is_scalar()) {
intrinsic->Parameters()[2]->Type()->is_scalar()) { f_id = GenerateSplat(f_id, builtin->Parameters()[0]->Type());
f_id = GenerateSplat(f_id, intrinsic->Parameters()[0]->Type());
if (f_id == 0) { if (f_id == 0) {
return 0; return 0;
} }
@ -2599,10 +2598,10 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
} }
return result_id; return result_id;
} }
case IntrinsicType::kReverseBits: case BuiltinType::kReverseBits:
op = spv::Op::OpBitReverse; op = spv::Op::OpBitReverse;
break; break;
case IntrinsicType::kSelect: { case BuiltinType::kSelect: {
// Note: Argument order is different in WGSL and SPIR-V // Note: Argument order is different in WGSL and SPIR-V
auto cond_id = get_arg_as_value_id(2); auto cond_id = get_arg_as_value_id(2);
auto true_id = get_arg_as_value_id(1); auto true_id = get_arg_as_value_id(1);
@ -2614,9 +2613,8 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
// If the condition is scalar but the objects are vectors, we need to // If the condition is scalar but the objects are vectors, we need to
// splat the condition into a vector of the same size. // splat the condition into a vector of the same size.
// TODO(jrprice): If we're targeting SPIR-V 1.4, we don't need to do this. // TODO(jrprice): If we're targeting SPIR-V 1.4, we don't need to do this.
auto* result_vector_type = intrinsic->ReturnType()->As<sem::Vector>(); auto* result_vector_type = builtin->ReturnType()->As<sem::Vector>();
if (result_vector_type && if (result_vector_type && builtin->Parameters()[2]->Type()->is_scalar()) {
intrinsic->Parameters()[2]->Type()->is_scalar()) {
auto* bool_vec_ty = builder_.create<sem::Vector>( auto* bool_vec_ty = builder_.create<sem::Vector>(
builder_.create<sem::Bool>(), result_vector_type->Width()); builder_.create<sem::Bool>(), result_vector_type->Width());
if (!GenerateTypeIfNeeded(bool_vec_ty)) { if (!GenerateTypeIfNeeded(bool_vec_ty)) {
@ -2636,25 +2634,25 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
} }
return result_id; return result_id;
} }
case IntrinsicType::kTranspose: case BuiltinType::kTranspose:
op = spv::Op::OpTranspose; op = spv::Op::OpTranspose;
break; break;
case IntrinsicType::kAbs: case BuiltinType::kAbs:
if (intrinsic->ReturnType()->is_unsigned_scalar_or_vector()) { if (builtin->ReturnType()->is_unsigned_scalar_or_vector()) {
// abs() only operates on *signed* integers. // abs() only operates on *signed* integers.
// This is a no-op for unsigned integers. // This is a no-op for unsigned integers.
return get_arg_as_value_id(0); return get_arg_as_value_id(0);
} }
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) { if (builtin->ReturnType()->is_float_scalar_or_vector()) {
glsl_std450(GLSLstd450FAbs); glsl_std450(GLSLstd450FAbs);
} else { } else {
glsl_std450(GLSLstd450SAbs); glsl_std450(GLSLstd450SAbs);
} }
break; break;
default: { default: {
auto inst_id = intrinsic_to_glsl_method(intrinsic); auto inst_id = builtin_to_glsl_method(builtin);
if (inst_id == 0) { if (inst_id == 0) {
error_ = "unknown method " + std::string(intrinsic->str()); error_ = "unknown method " + std::string(builtin->str());
return 0; return 0;
} }
glsl_std450(inst_id); glsl_std450(inst_id);
@ -2663,8 +2661,7 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
} }
if (op == spv::Op::OpNop) { if (op == spv::Op::OpNop) {
error_ = error_ = "unable to determine operator for: " + std::string(builtin->str());
"unable to determine operator for: " + std::string(intrinsic->str());
return 0; return 0;
} }
@ -2683,13 +2680,13 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
return result_id; return result_id;
} }
bool Builder::GenerateTextureIntrinsic(const sem::Call* call, bool Builder::GenerateTextureBuiltin(const sem::Call* call,
const sem::Intrinsic* intrinsic, const sem::Builtin* builtin,
Operand result_type, Operand result_type,
Operand result_id) { Operand result_id) {
using Usage = sem::ParameterUsage; using Usage = sem::ParameterUsage;
auto& signature = intrinsic->Signature(); auto& signature = builtin->Signature();
auto& arguments = call->Arguments(); auto& arguments = call->Arguments();
// Generates the given expression, returning the operand ID // Generates the given expression, returning the operand ID
@ -2723,7 +2720,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
auto op = spv::Op::OpNop; auto op = spv::Op::OpNop;
// Custom function to call after the texture-intrinsic op has been generated. // Custom function to call after the texture-builtin op has been generated.
std::function<bool()> post_emission = [] { return true; }; std::function<bool()> post_emission = [] { return true; };
// Populate the spirv_params with common parameters // Populate the spirv_params with common parameters
@ -2848,8 +2845,8 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
return append_coords_to_spirv_params(); return append_coords_to_spirv_params();
}; };
switch (intrinsic->Type()) { switch (builtin->Type()) {
case IntrinsicType::kTextureDimensions: { case BuiltinType::kTextureDimensions: {
// Number of returned elements from OpImageQuerySize[Lod] may not match // Number of returned elements from OpImageQuerySize[Lod] may not match
// those of textureDimensions(). // those of textureDimensions().
// This might be due to an extra vector scalar describing the number of // This might be due to an extra vector scalar describing the number of
@ -2896,7 +2893,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
} }
break; break;
} }
case IntrinsicType::kTextureNumLayers: { case BuiltinType::kTextureNumLayers: {
uint32_t spirv_dims = 0; uint32_t spirv_dims = 0;
switch (texture_type->dim()) { switch (texture_type->dim()) {
default: default:
@ -2928,19 +2925,19 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
} }
break; break;
} }
case IntrinsicType::kTextureNumLevels: { case BuiltinType::kTextureNumLevels: {
op = spv::Op::OpImageQueryLevels; op = spv::Op::OpImageQueryLevels;
append_result_type_and_id_to_spirv_params(); append_result_type_and_id_to_spirv_params();
spirv_params.emplace_back(gen_arg(Usage::kTexture)); spirv_params.emplace_back(gen_arg(Usage::kTexture));
break; break;
} }
case IntrinsicType::kTextureNumSamples: { case BuiltinType::kTextureNumSamples: {
op = spv::Op::OpImageQuerySamples; op = spv::Op::OpImageQuerySamples;
append_result_type_and_id_to_spirv_params(); append_result_type_and_id_to_spirv_params();
spirv_params.emplace_back(gen_arg(Usage::kTexture)); spirv_params.emplace_back(gen_arg(Usage::kTexture));
break; break;
} }
case IntrinsicType::kTextureLoad: { case BuiltinType::kTextureLoad: {
op = texture_type->Is<sem::StorageTexture>() ? spv::Op::OpImageRead op = texture_type->Is<sem::StorageTexture>() ? spv::Op::OpImageRead
: spv::Op::OpImageFetch; : spv::Op::OpImageFetch;
append_result_type_and_id_to_spirv_params_for_read(); append_result_type_and_id_to_spirv_params_for_read();
@ -2961,7 +2958,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
break; break;
} }
case IntrinsicType::kTextureStore: { case BuiltinType::kTextureStore: {
op = spv::Op::OpImageWrite; op = spv::Op::OpImageWrite;
spirv_params.emplace_back(gen_arg(Usage::kTexture)); spirv_params.emplace_back(gen_arg(Usage::kTexture));
if (!append_coords_to_spirv_params()) { if (!append_coords_to_spirv_params()) {
@ -2970,7 +2967,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
spirv_params.emplace_back(gen_arg(Usage::kValue)); spirv_params.emplace_back(gen_arg(Usage::kValue));
break; break;
} }
case IntrinsicType::kTextureGather: { case BuiltinType::kTextureGather: {
op = spv::Op::OpImageGather; op = spv::Op::OpImageGather;
append_result_type_and_id_to_spirv_params(); append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) { if (!append_image_and_coords_to_spirv_params()) {
@ -2984,7 +2981,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
} }
break; break;
} }
case IntrinsicType::kTextureGatherCompare: { case BuiltinType::kTextureGatherCompare: {
op = spv::Op::OpImageDrefGather; op = spv::Op::OpImageDrefGather;
append_result_type_and_id_to_spirv_params(); append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) { if (!append_image_and_coords_to_spirv_params()) {
@ -2993,7 +2990,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
spirv_params.emplace_back(gen_arg(Usage::kDepthRef)); spirv_params.emplace_back(gen_arg(Usage::kDepthRef));
break; break;
} }
case IntrinsicType::kTextureSample: { case BuiltinType::kTextureSample: {
op = spv::Op::OpImageSampleImplicitLod; op = spv::Op::OpImageSampleImplicitLod;
append_result_type_and_id_to_spirv_params_for_read(); append_result_type_and_id_to_spirv_params_for_read();
if (!append_image_and_coords_to_spirv_params()) { if (!append_image_and_coords_to_spirv_params()) {
@ -3001,7 +2998,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
} }
break; break;
} }
case IntrinsicType::kTextureSampleBias: { case BuiltinType::kTextureSampleBias: {
op = spv::Op::OpImageSampleImplicitLod; op = spv::Op::OpImageSampleImplicitLod;
append_result_type_and_id_to_spirv_params_for_read(); append_result_type_and_id_to_spirv_params_for_read();
if (!append_image_and_coords_to_spirv_params()) { if (!append_image_and_coords_to_spirv_params()) {
@ -3011,7 +3008,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
ImageOperand{SpvImageOperandsBiasMask, gen_arg(Usage::kBias)}); ImageOperand{SpvImageOperandsBiasMask, gen_arg(Usage::kBias)});
break; break;
} }
case IntrinsicType::kTextureSampleLevel: { case BuiltinType::kTextureSampleLevel: {
op = spv::Op::OpImageSampleExplicitLod; op = spv::Op::OpImageSampleExplicitLod;
append_result_type_and_id_to_spirv_params_for_read(); append_result_type_and_id_to_spirv_params_for_read();
if (!append_image_and_coords_to_spirv_params()) { if (!append_image_and_coords_to_spirv_params()) {
@ -3037,7 +3034,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
image_operands.emplace_back(ImageOperand{SpvImageOperandsLodMask, level}); image_operands.emplace_back(ImageOperand{SpvImageOperandsLodMask, level});
break; break;
} }
case IntrinsicType::kTextureSampleGrad: { case BuiltinType::kTextureSampleGrad: {
op = spv::Op::OpImageSampleExplicitLod; op = spv::Op::OpImageSampleExplicitLod;
append_result_type_and_id_to_spirv_params_for_read(); append_result_type_and_id_to_spirv_params_for_read();
if (!append_image_and_coords_to_spirv_params()) { if (!append_image_and_coords_to_spirv_params()) {
@ -3049,7 +3046,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
ImageOperand{SpvImageOperandsGradMask, gen_arg(Usage::kDdy)}); ImageOperand{SpvImageOperandsGradMask, gen_arg(Usage::kDdy)});
break; break;
} }
case IntrinsicType::kTextureSampleCompare: { case BuiltinType::kTextureSampleCompare: {
op = spv::Op::OpImageSampleDrefImplicitLod; op = spv::Op::OpImageSampleDrefImplicitLod;
append_result_type_and_id_to_spirv_params(); append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) { if (!append_image_and_coords_to_spirv_params()) {
@ -3058,7 +3055,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
spirv_params.emplace_back(gen_arg(Usage::kDepthRef)); spirv_params.emplace_back(gen_arg(Usage::kDepthRef));
break; break;
} }
case IntrinsicType::kTextureSampleCompareLevel: { case BuiltinType::kTextureSampleCompareLevel: {
op = spv::Op::OpImageSampleDrefExplicitLod; op = spv::Op::OpImageSampleDrefExplicitLod;
append_result_type_and_id_to_spirv_params(); append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) { if (!append_image_and_coords_to_spirv_params()) {
@ -3096,8 +3093,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
} }
if (op == spv::Op::OpNop) { if (op == spv::Op::OpNop) {
error_ = error_ = "unable to determine operator for: " + std::string(builtin->str());
"unable to determine operator for: " + std::string(intrinsic->str());
return false; return false;
} }
@ -3108,7 +3104,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
return post_emission(); return post_emission();
} }
bool Builder::GenerateControlBarrierIntrinsic(const sem::Intrinsic* intrinsic) { bool Builder::GenerateControlBarrierBuiltin(const sem::Builtin* builtin) {
auto const op = spv::Op::OpControlBarrier; auto const op = spv::Op::OpControlBarrier;
uint32_t execution = 0; uint32_t execution = 0;
uint32_t memory = 0; uint32_t memory = 0;
@ -3116,21 +3112,21 @@ bool Builder::GenerateControlBarrierIntrinsic(const sem::Intrinsic* intrinsic) {
// TODO(crbug.com/tint/661): Combine sequential barriers to a single // TODO(crbug.com/tint/661): Combine sequential barriers to a single
// instruction. // instruction.
if (intrinsic->Type() == sem::IntrinsicType::kWorkgroupBarrier) { if (builtin->Type() == sem::BuiltinType::kWorkgroupBarrier) {
execution = static_cast<uint32_t>(spv::Scope::Workgroup); execution = static_cast<uint32_t>(spv::Scope::Workgroup);
memory = static_cast<uint32_t>(spv::Scope::Workgroup); memory = static_cast<uint32_t>(spv::Scope::Workgroup);
semantics = semantics =
static_cast<uint32_t>(spv::MemorySemanticsMask::AcquireRelease) | static_cast<uint32_t>(spv::MemorySemanticsMask::AcquireRelease) |
static_cast<uint32_t>(spv::MemorySemanticsMask::WorkgroupMemory); static_cast<uint32_t>(spv::MemorySemanticsMask::WorkgroupMemory);
} else if (intrinsic->Type() == sem::IntrinsicType::kStorageBarrier) { } else if (builtin->Type() == sem::BuiltinType::kStorageBarrier) {
execution = static_cast<uint32_t>(spv::Scope::Workgroup); execution = static_cast<uint32_t>(spv::Scope::Workgroup);
memory = static_cast<uint32_t>(spv::Scope::Workgroup); memory = static_cast<uint32_t>(spv::Scope::Workgroup);
semantics = semantics =
static_cast<uint32_t>(spv::MemorySemanticsMask::AcquireRelease) | static_cast<uint32_t>(spv::MemorySemanticsMask::AcquireRelease) |
static_cast<uint32_t>(spv::MemorySemanticsMask::UniformMemory); static_cast<uint32_t>(spv::MemorySemanticsMask::UniformMemory);
} else { } else {
error_ = "unexpected barrier intrinsic type "; error_ = "unexpected barrier builtin type ";
error_ += sem::str(intrinsic->Type()); error_ += sem::str(builtin->Type());
return false; return false;
} }
@ -3148,20 +3144,20 @@ bool Builder::GenerateControlBarrierIntrinsic(const sem::Intrinsic* intrinsic) {
}); });
} }
bool Builder::GenerateAtomicIntrinsic(const sem::Call* call, bool Builder::GenerateAtomicBuiltin(const sem::Call* call,
const sem::Intrinsic* intrinsic, const sem::Builtin* builtin,
Operand result_type, Operand result_type,
Operand result_id) { Operand result_id) {
auto is_value_signed = [&] { auto is_value_signed = [&] {
return intrinsic->Parameters()[1]->Type()->Is<sem::I32>(); return builtin->Parameters()[1]->Type()->Is<sem::I32>();
}; };
auto storage_class = auto storage_class =
intrinsic->Parameters()[0]->Type()->As<sem::Pointer>()->StorageClass(); builtin->Parameters()[0]->Type()->As<sem::Pointer>()->StorageClass();
uint32_t memory_id = 0; uint32_t memory_id = 0;
switch ( switch (
intrinsic->Parameters()[0]->Type()->As<sem::Pointer>()->StorageClass()) { builtin->Parameters()[0]->Type()->As<sem::Pointer>()->StorageClass()) {
case ast::StorageClass::kWorkgroup: case ast::StorageClass::kWorkgroup:
memory_id = GenerateConstantIfNeeded( memory_id = GenerateConstantIfNeeded(
ScalarConstant::U32(static_cast<uint32_t>(spv::Scope::Workgroup))); ScalarConstant::U32(static_cast<uint32_t>(spv::Scope::Workgroup)));
@ -3203,8 +3199,8 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
Operand memory = Operand::Int(memory_id); Operand memory = Operand::Int(memory_id);
Operand semantics = Operand::Int(semantics_id); Operand semantics = Operand::Int(semantics_id);
switch (intrinsic->Type()) { switch (builtin->Type()) {
case sem::IntrinsicType::kAtomicLoad: case sem::BuiltinType::kAtomicLoad:
return push_function_inst(spv::Op::OpAtomicLoad, { return push_function_inst(spv::Op::OpAtomicLoad, {
result_type, result_type,
result_id, result_id,
@ -3212,14 +3208,14 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
memory, memory,
semantics, semantics,
}); });
case sem::IntrinsicType::kAtomicStore: case sem::BuiltinType::kAtomicStore:
return push_function_inst(spv::Op::OpAtomicStore, { return push_function_inst(spv::Op::OpAtomicStore, {
pointer, pointer,
memory, memory,
semantics, semantics,
value, value,
}); });
case sem::IntrinsicType::kAtomicAdd: case sem::BuiltinType::kAtomicAdd:
return push_function_inst(spv::Op::OpAtomicIAdd, { return push_function_inst(spv::Op::OpAtomicIAdd, {
result_type, result_type,
result_id, result_id,
@ -3228,7 +3224,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
semantics, semantics,
value, value,
}); });
case sem::IntrinsicType::kAtomicSub: case sem::BuiltinType::kAtomicSub:
return push_function_inst(spv::Op::OpAtomicISub, { return push_function_inst(spv::Op::OpAtomicISub, {
result_type, result_type,
result_id, result_id,
@ -3237,7 +3233,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
semantics, semantics,
value, value,
}); });
case sem::IntrinsicType::kAtomicMax: case sem::BuiltinType::kAtomicMax:
return push_function_inst( return push_function_inst(
is_value_signed() ? spv::Op::OpAtomicSMax : spv::Op::OpAtomicUMax, is_value_signed() ? spv::Op::OpAtomicSMax : spv::Op::OpAtomicUMax,
{ {
@ -3248,7 +3244,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
semantics, semantics,
value, value,
}); });
case sem::IntrinsicType::kAtomicMin: case sem::BuiltinType::kAtomicMin:
return push_function_inst( return push_function_inst(
is_value_signed() ? spv::Op::OpAtomicSMin : spv::Op::OpAtomicUMin, is_value_signed() ? spv::Op::OpAtomicSMin : spv::Op::OpAtomicUMin,
{ {
@ -3259,7 +3255,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
semantics, semantics,
value, value,
}); });
case sem::IntrinsicType::kAtomicAnd: case sem::BuiltinType::kAtomicAnd:
return push_function_inst(spv::Op::OpAtomicAnd, { return push_function_inst(spv::Op::OpAtomicAnd, {
result_type, result_type,
result_id, result_id,
@ -3268,7 +3264,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
semantics, semantics,
value, value,
}); });
case sem::IntrinsicType::kAtomicOr: case sem::BuiltinType::kAtomicOr:
return push_function_inst(spv::Op::OpAtomicOr, { return push_function_inst(spv::Op::OpAtomicOr, {
result_type, result_type,
result_id, result_id,
@ -3277,7 +3273,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
semantics, semantics,
value, value,
}); });
case sem::IntrinsicType::kAtomicXor: case sem::BuiltinType::kAtomicXor:
return push_function_inst(spv::Op::OpAtomicXor, { return push_function_inst(spv::Op::OpAtomicXor, {
result_type, result_type,
result_id, result_id,
@ -3286,7 +3282,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
semantics, semantics,
value, value,
}); });
case sem::IntrinsicType::kAtomicExchange: case sem::BuiltinType::kAtomicExchange:
return push_function_inst(spv::Op::OpAtomicExchange, { return push_function_inst(spv::Op::OpAtomicExchange, {
result_type, result_type,
result_id, result_id,
@ -3295,7 +3291,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
semantics, semantics,
value, value,
}); });
case sem::IntrinsicType::kAtomicCompareExchangeWeak: { case sem::BuiltinType::kAtomicCompareExchangeWeak: {
auto comparator = GenerateExpression(call->Arguments()[1]->Declaration()); auto comparator = GenerateExpression(call->Arguments()[1]->Declaration());
if (comparator == 0) { if (comparator == 0) {
return false; return false;
@ -3383,7 +3379,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
} }
default: default:
TINT_UNREACHABLE(Writer, builder_.Diagnostics()) TINT_UNREACHABLE(Writer, builder_.Diagnostics())
<< "unhandled atomic intrinsic " << intrinsic->Type(); << "unhandled atomic builtin " << builtin->Type();
return false; return false;
} }
} }

View File

@ -35,7 +35,7 @@
#include "src/ast/variable_decl_statement.h" #include "src/ast/variable_decl_statement.h"
#include "src/program_builder.h" #include "src/program_builder.h"
#include "src/scope_stack.h" #include "src/scope_stack.h"
#include "src/sem/intrinsic.h" #include "src/sem/builtin.h"
#include "src/sem/storage_texture_type.h" #include "src/sem/storage_texture_type.h"
#include "src/writer/spirv/function.h" #include "src/writer/spirv/function.h"
#include "src/writer/spirv/scalar_constant.h" #include "src/writer/spirv/scalar_constant.h"
@ -376,44 +376,44 @@ class Builder {
/// @returns the expression ID on success or 0 otherwise /// @returns the expression ID on success or 0 otherwise
uint32_t GenerateFunctionCall(const sem::Call* call, uint32_t GenerateFunctionCall(const sem::Call* call,
const sem::Function* function); const sem::Function* function);
/// Handles generating an intrinsic call expression /// Handles generating a builtin call expression
/// @param call the call expression /// @param call the call expression
/// @param intrinsic the intrinsic being called /// @param builtin the builtin being called
/// @returns the expression ID on success or 0 otherwise /// @returns the expression ID on success or 0 otherwise
uint32_t GenerateIntrinsicCall(const sem::Call* call, uint32_t GenerateBuiltinCall(const sem::Call* call,
const sem::Intrinsic* intrinsic); const sem::Builtin* builtin);
/// Handles generating a type constructor or type conversion expression /// Handles generating a type constructor or type conversion expression
/// @param call the call expression /// @param call the call expression
/// @param var the variable that is being initialized. May be null. /// @param var the variable that is being initialized. May be null.
/// @returns the expression ID on success or 0 otherwise /// @returns the expression ID on success or 0 otherwise
uint32_t GenerateTypeConstructorOrConversion(const sem::Call* call, uint32_t GenerateTypeConstructorOrConversion(const sem::Call* call,
const ast::Variable* var); const ast::Variable* var);
/// Generates a texture intrinsic call. Emits an error and returns false if /// Generates a texture builtin call. Emits an error and returns false if
/// we're currently outside a function. /// we're currently outside a function.
/// @param call the call expression /// @param call the call expression
/// @param intrinsic the semantic information for the texture intrinsic /// @param builtin the semantic information for the texture builtin
/// @param result_type result type operand of the texture instruction /// @param result_type result type operand of the texture instruction
/// @param result_id result identifier operand of the texture instruction /// @param result_id result identifier operand of the texture instruction
/// parameters /// parameters
/// @returns true on success /// @returns true on success
bool GenerateTextureIntrinsic(const sem::Call* call, bool GenerateTextureBuiltin(const sem::Call* call,
const sem::Intrinsic* intrinsic, const sem::Builtin* builtin,
spirv::Operand result_type, spirv::Operand result_type,
spirv::Operand result_id); spirv::Operand result_id);
/// Generates a control barrier statement. /// Generates a control barrier statement.
/// @param intrinsic the semantic information for the barrier intrinsic call /// @param builtin the semantic information for the barrier builtin call
/// @returns true on success /// @returns true on success
bool GenerateControlBarrierIntrinsic(const sem::Intrinsic* intrinsic); bool GenerateControlBarrierBuiltin(const sem::Builtin* builtin);
/// Generates an atomic intrinsic call. /// Generates an atomic builtin call.
/// @param call the call expression /// @param call the call expression
/// @param intrinsic the semantic information for the atomic intrinsic call /// @param builtin the semantic information for the atomic builtin call
/// @param result_type result type operand of the texture instruction /// @param result_type result type operand of the texture instruction
/// @param result_id result identifier operand of the texture instruction /// @param result_id result identifier operand of the texture instruction
/// @returns true on success /// @returns true on success
bool GenerateAtomicIntrinsic(const sem::Call* call, bool GenerateAtomicBuiltin(const sem::Call* call,
const sem::Intrinsic* intrinsic, const sem::Builtin* builtin,
Operand result_type, Operand result_type,
Operand result_id); Operand result_id);
/// Generates a sampled image /// Generates a sampled image
/// @param texture_type the texture type /// @param texture_type the texture type
/// @param texture_operand the texture operand /// @param texture_operand the texture operand

View File

@ -25,22 +25,22 @@ namespace writer {
namespace spirv { namespace spirv {
namespace { namespace {
using IntrinsicBuilderTest = TestHelper; using BuiltinBuilderTest = TestHelper;
template <typename T> template <typename T>
using IntrinsicBuilderTestWithParam = TestParamHelper<T>; using BuiltinBuilderTestWithParam = TestParamHelper<T>;
struct IntrinsicData { struct BuiltinData {
std::string name; std::string name;
std::string op; std::string op;
}; };
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) { inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
out << data.name; out << data.name;
return out; return out;
} }
using IntrinsicBoolTest = IntrinsicBuilderTestWithParam<IntrinsicData>; using BuiltinBoolTest = BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(IntrinsicBoolTest, Call_Bool_Scalar) { TEST_P(BuiltinBoolTest, Call_Bool_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* var = Global("v", ty.bool_(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.bool_(), ast::StorageClass::kPrivate);
auto* expr = Call(param.name, "v"); auto* expr = Call(param.name, "v");
@ -67,7 +67,7 @@ TEST_P(IntrinsicBoolTest, Call_Bool_Scalar) {
"%10 = OpLoad %3 %1\nOpReturn\n"); "%10 = OpLoad %3 %1\nOpReturn\n");
} }
TEST_P(IntrinsicBoolTest, Call_Bool_Vector) { TEST_P(BuiltinBoolTest, Call_Bool_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* var = Global("v", ty.vec3<bool>(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.vec3<bool>(), ast::StorageClass::kPrivate);
auto* expr = Call(param.name, "v"); auto* expr = Call(param.name, "v");
@ -97,13 +97,13 @@ OpReturn
"${op}", param.op); "${op}", param.op);
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected); EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
} }
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest, INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
IntrinsicBoolTest, BuiltinBoolTest,
testing::Values(IntrinsicData{"any", "OpAny"}, testing::Values(BuiltinData{"any", "OpAny"},
IntrinsicData{"all", "OpAll"})); BuiltinData{"all", "OpAll"}));
using IntrinsicFloatTest = IntrinsicBuilderTestWithParam<IntrinsicData>; using BuiltinFloatTest = BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(IntrinsicFloatTest, Call_Float_Scalar) { TEST_P(BuiltinFloatTest, Call_Float_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
auto* expr = Call(param.name, "v"); auto* expr = Call(param.name, "v");
@ -134,7 +134,7 @@ OpReturn
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected); EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
} }
TEST_P(IntrinsicFloatTest, Call_Float_Vector) { TEST_P(BuiltinFloatTest, Call_Float_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate);
auto* expr = Call(param.name, "v"); auto* expr = Call(param.name, "v");
@ -166,12 +166,12 @@ OpReturn
"${op}", param.op); "${op}", param.op);
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected); EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
} }
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest, INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
IntrinsicFloatTest, BuiltinFloatTest,
testing::Values(IntrinsicData{"isNan", "OpIsNan"}, testing::Values(BuiltinData{"isNan", "OpIsNan"},
IntrinsicData{"isInf", "OpIsInf"})); BuiltinData{"isInf", "OpIsInf"}));
TEST_F(IntrinsicBuilderTest, IsFinite_Scalar) { TEST_F(BuiltinBuilderTest, IsFinite_Scalar) {
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
auto* expr = Call("isFinite", "v"); auto* expr = Call("isFinite", "v");
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -202,7 +202,7 @@ OpReturn
)"); )");
} }
TEST_F(IntrinsicBuilderTest, IsFinite_Vector) { TEST_F(BuiltinBuilderTest, IsFinite_Vector) {
auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate);
auto* expr = Call("isFinite", "v"); auto* expr = Call("isFinite", "v");
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -235,7 +235,7 @@ OpReturn
)"); )");
} }
TEST_F(IntrinsicBuilderTest, IsNormal_Scalar) { TEST_F(BuiltinBuilderTest, IsNormal_Scalar) {
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
auto* expr = Call("isNormal", "v"); auto* expr = Call("isNormal", "v");
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -275,7 +275,7 @@ OpFunctionEnd
)"); )");
} }
TEST_F(IntrinsicBuilderTest, IsNormal_Vector) { TEST_F(BuiltinBuilderTest, IsNormal_Vector) {
auto* var = Global("v", ty.vec2<f32>(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.vec2<f32>(), ast::StorageClass::kPrivate);
auto* expr = Call("isNormal", "v"); auto* expr = Call("isNormal", "v");
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -321,8 +321,8 @@ OpFunctionEnd
)"); )");
} }
using IntrinsicIntTest = IntrinsicBuilderTestWithParam<IntrinsicData>; using BuiltinIntTest = BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(IntrinsicIntTest, Call_SInt_Scalar) { TEST_P(BuiltinIntTest, Call_SInt_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* var = Global("v", ty.i32(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.i32(), ast::StorageClass::kPrivate);
auto* expr = Call(param.name, "v"); auto* expr = Call(param.name, "v");
@ -352,7 +352,7 @@ OpReturn
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected); EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
} }
TEST_P(IntrinsicIntTest, Call_SInt_Vector) { TEST_P(BuiltinIntTest, Call_SInt_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* var = Global("v", ty.vec3<i32>(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.vec3<i32>(), ast::StorageClass::kPrivate);
auto* expr = Call(param.name, "v"); auto* expr = Call(param.name, "v");
@ -383,7 +383,7 @@ OpReturn
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected); EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
} }
TEST_P(IntrinsicIntTest, Call_UInt_Scalar) { TEST_P(BuiltinIntTest, Call_UInt_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* var = Global("v", ty.u32(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.u32(), ast::StorageClass::kPrivate);
auto* expr = Call(param.name, "v"); auto* expr = Call(param.name, "v");
@ -413,7 +413,7 @@ OpReturn
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected); EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
} }
TEST_P(IntrinsicIntTest, Call_UInt_Vector) { TEST_P(BuiltinIntTest, Call_UInt_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* var = Global("v", ty.vec3<u32>(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.vec3<u32>(), ast::StorageClass::kPrivate);
auto* expr = Call(param.name, "v"); auto* expr = Call(param.name, "v");
@ -444,12 +444,12 @@ OpReturn
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected); EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
IntrinsicBuilderTest, BuiltinBuilderTest,
IntrinsicIntTest, BuiltinIntTest,
testing::Values(IntrinsicData{"countOneBits", "OpBitCount"}, testing::Values(BuiltinData{"countOneBits", "OpBitCount"},
IntrinsicData{"reverseBits", "OpBitReverse"})); BuiltinData{"reverseBits", "OpBitReverse"}));
TEST_F(IntrinsicBuilderTest, Call_Dot_F32) { TEST_F(BuiltinBuilderTest, Call_Dot_F32) {
auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate);
auto* expr = Call("dot", "v", "v"); auto* expr = Call("dot", "v", "v");
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -478,7 +478,7 @@ OpReturn
)"); )");
} }
TEST_F(IntrinsicBuilderTest, Call_Dot_U32) { TEST_F(BuiltinBuilderTest, Call_Dot_U32) {
auto* var = Global("v", ty.vec3<u32>(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.vec3<u32>(), ast::StorageClass::kPrivate);
auto* expr = Call("dot", "v", "v"); auto* expr = Call("dot", "v", "v");
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -517,7 +517,7 @@ OpReturn
)"); )");
} }
TEST_F(IntrinsicBuilderTest, Call_Dot_I32) { TEST_F(BuiltinBuilderTest, Call_Dot_I32) {
auto* var = Global("v", ty.vec3<i32>(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.vec3<i32>(), ast::StorageClass::kPrivate);
auto* expr = Call("dot", "v", "v"); auto* expr = Call("dot", "v", "v");
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -556,8 +556,8 @@ OpReturn
)"); )");
} }
using IntrinsicDeriveTest = IntrinsicBuilderTestWithParam<IntrinsicData>; using BuiltinDeriveTest = BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(IntrinsicDeriveTest, Call_Derivative_Scalar) { TEST_P(BuiltinDeriveTest, Call_Derivative_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
auto* expr = Call(param.name, "v"); auto* expr = Call(param.name, "v");
@ -585,7 +585,7 @@ OpReturn
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected); EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
} }
TEST_P(IntrinsicDeriveTest, Call_Derivative_Vector) { TEST_P(BuiltinDeriveTest, Call_Derivative_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate); auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate);
auto* expr = Call(param.name, "v"); auto* expr = Call(param.name, "v");
@ -620,19 +620,19 @@ OpReturn
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected); EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
IntrinsicBuilderTest, BuiltinBuilderTest,
IntrinsicDeriveTest, BuiltinDeriveTest,
testing::Values(IntrinsicData{"dpdx", "OpDPdx"}, testing::Values(BuiltinData{"dpdx", "OpDPdx"},
IntrinsicData{"dpdxFine", "OpDPdxFine"}, BuiltinData{"dpdxFine", "OpDPdxFine"},
IntrinsicData{"dpdxCoarse", "OpDPdxCoarse"}, BuiltinData{"dpdxCoarse", "OpDPdxCoarse"},
IntrinsicData{"dpdy", "OpDPdy"}, BuiltinData{"dpdy", "OpDPdy"},
IntrinsicData{"dpdyFine", "OpDPdyFine"}, BuiltinData{"dpdyFine", "OpDPdyFine"},
IntrinsicData{"dpdyCoarse", "OpDPdyCoarse"}, BuiltinData{"dpdyCoarse", "OpDPdyCoarse"},
IntrinsicData{"fwidth", "OpFwidth"}, BuiltinData{"fwidth", "OpFwidth"},
IntrinsicData{"fwidthFine", "OpFwidthFine"}, BuiltinData{"fwidthFine", "OpFwidthFine"},
IntrinsicData{"fwidthCoarse", "OpFwidthCoarse"})); BuiltinData{"fwidthCoarse", "OpFwidthCoarse"}));
TEST_F(IntrinsicBuilderTest, Call_Select) { TEST_F(BuiltinBuilderTest, Call_Select) {
auto* v3 = Global("v3", ty.vec3<f32>(), ast::StorageClass::kPrivate); auto* v3 = Global("v3", ty.vec3<f32>(), ast::StorageClass::kPrivate);
auto* bool_v3 = auto* bool_v3 =
@ -672,7 +672,7 @@ OpReturn
} }
// This tests that we do not push OpTypeSampledImage and float_0 type twice. // This tests that we do not push OpTypeSampledImage and float_0 type twice.
TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) { TEST_F(BuiltinBuilderTest, Call_TextureSampleCompare_Twice) {
auto* s = ty.sampler(ast::SamplerKind::kComparisonSampler); auto* s = ty.sampler(ast::SamplerKind::kComparisonSampler);
auto* t = ty.depth_texture(ast::TextureDimension::k2d); auto* t = ty.depth_texture(ast::TextureDimension::k2d);
@ -732,7 +732,7 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) {
)"); )");
} }
TEST_F(IntrinsicBuilderTest, Call_GLSLMethod_WithLoad) { TEST_F(BuiltinBuilderTest, Call_GLSLMethod_WithLoad) {
auto* var = Global("ident", ty.f32(), ast::StorageClass::kPrivate); auto* var = Global("ident", ty.f32(), ast::StorageClass::kPrivate);
auto* expr = Call("round", "ident"); auto* expr = Call("round", "ident");
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -763,9 +763,9 @@ OpFunctionEnd
)"); )");
} }
using Intrinsic_Builtin_SingleParam_Float_Test = using Builtin_Builtin_SingleParam_Float_Test =
IntrinsicBuilderTestWithParam<IntrinsicData>; BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(Intrinsic_Builtin_SingleParam_Float_Test, Call_Scalar) { TEST_P(Builtin_Builtin_SingleParam_Float_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, 1.0f); auto* expr = Call(param.name, 1.0f);
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -792,7 +792,7 @@ OpFunctionEnd
)"); )");
} }
TEST_P(Intrinsic_Builtin_SingleParam_Float_Test, Call_Vector) { TEST_P(Builtin_Builtin_SingleParam_Float_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, vec2<f32>(1.0f, 1.0f)); auto* expr = Call(param.name, vec2<f32>(1.0f, 1.0f));
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -820,35 +820,35 @@ OpReturn
OpFunctionEnd OpFunctionEnd
)"); )");
} }
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest, INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
Intrinsic_Builtin_SingleParam_Float_Test, Builtin_Builtin_SingleParam_Float_Test,
testing::Values(IntrinsicData{"abs", "FAbs"}, testing::Values(BuiltinData{"abs", "FAbs"},
IntrinsicData{"acos", "Acos"}, BuiltinData{"acos", "Acos"},
IntrinsicData{"asin", "Asin"}, BuiltinData{"asin", "Asin"},
IntrinsicData{"atan", "Atan"}, BuiltinData{"atan", "Atan"},
IntrinsicData{"ceil", "Ceil"}, BuiltinData{"ceil", "Ceil"},
IntrinsicData{"cos", "Cos"}, BuiltinData{"cos", "Cos"},
IntrinsicData{"cosh", "Cosh"}, BuiltinData{"cosh", "Cosh"},
IntrinsicData{"degrees", "Degrees"}, BuiltinData{"degrees", "Degrees"},
IntrinsicData{"exp", "Exp"}, BuiltinData{"exp", "Exp"},
IntrinsicData{"exp2", "Exp2"}, BuiltinData{"exp2", "Exp2"},
IntrinsicData{"floor", "Floor"}, BuiltinData{"floor", "Floor"},
IntrinsicData{"fract", "Fract"}, BuiltinData{"fract", "Fract"},
IntrinsicData{"inverseSqrt", BuiltinData{"inverseSqrt",
"InverseSqrt"}, "InverseSqrt"},
IntrinsicData{"log", "Log"}, BuiltinData{"log", "Log"},
IntrinsicData{"log2", "Log2"}, BuiltinData{"log2", "Log2"},
IntrinsicData{"radians", "Radians"}, BuiltinData{"radians", "Radians"},
IntrinsicData{"round", "RoundEven"}, BuiltinData{"round", "RoundEven"},
IntrinsicData{"sign", "FSign"}, BuiltinData{"sign", "FSign"},
IntrinsicData{"sin", "Sin"}, BuiltinData{"sin", "Sin"},
IntrinsicData{"sinh", "Sinh"}, BuiltinData{"sinh", "Sinh"},
IntrinsicData{"sqrt", "Sqrt"}, BuiltinData{"sqrt", "Sqrt"},
IntrinsicData{"tan", "Tan"}, BuiltinData{"tan", "Tan"},
IntrinsicData{"tanh", "Tanh"}, BuiltinData{"tanh", "Tanh"},
IntrinsicData{"trunc", "Trunc"})); BuiltinData{"trunc", "Trunc"}));
TEST_F(IntrinsicBuilderTest, Call_Length_Scalar) { TEST_F(BuiltinBuilderTest, Call_Length_Scalar) {
auto* expr = Call("length", 1.0f); auto* expr = Call("length", 1.0f);
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
{ {
@ -873,7 +873,7 @@ OpFunctionEnd
)"); )");
} }
TEST_F(IntrinsicBuilderTest, Call_Length_Vector) { TEST_F(BuiltinBuilderTest, Call_Length_Vector) {
auto* expr = Call("length", vec2<f32>(1.0f, 1.0f)); auto* expr = Call("length", vec2<f32>(1.0f, 1.0f));
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
{ {
@ -900,7 +900,7 @@ OpFunctionEnd
)"); )");
} }
TEST_F(IntrinsicBuilderTest, Call_Normalize) { TEST_F(BuiltinBuilderTest, Call_Normalize) {
auto* expr = Call("normalize", vec2<f32>(1.0f, 1.0f)); auto* expr = Call("normalize", vec2<f32>(1.0f, 1.0f));
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
{ {
@ -927,9 +927,9 @@ OpFunctionEnd
)"); )");
} }
using Intrinsic_Builtin_DualParam_Float_Test = using Builtin_Builtin_DualParam_Float_Test =
IntrinsicBuilderTestWithParam<IntrinsicData>; BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(Intrinsic_Builtin_DualParam_Float_Test, Call_Scalar) { TEST_P(Builtin_Builtin_DualParam_Float_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, 1.0f, 1.0f); auto* expr = Call(param.name, 1.0f, 1.0f);
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -956,7 +956,7 @@ OpFunctionEnd
)"); )");
} }
TEST_P(Intrinsic_Builtin_DualParam_Float_Test, Call_Vector) { TEST_P(Builtin_Builtin_DualParam_Float_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f)); auto* expr = Call(param.name, vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f));
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -984,15 +984,15 @@ OpReturn
OpFunctionEnd OpFunctionEnd
)"); )");
} }
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest, INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
Intrinsic_Builtin_DualParam_Float_Test, Builtin_Builtin_DualParam_Float_Test,
testing::Values(IntrinsicData{"atan2", "Atan2"}, testing::Values(BuiltinData{"atan2", "Atan2"},
IntrinsicData{"max", "NMax"}, BuiltinData{"max", "NMax"},
IntrinsicData{"min", "NMin"}, BuiltinData{"min", "NMin"},
IntrinsicData{"pow", "Pow"}, BuiltinData{"pow", "Pow"},
IntrinsicData{"step", "Step"})); BuiltinData{"step", "Step"}));
TEST_F(IntrinsicBuilderTest, Call_Reflect_Vector) { TEST_F(BuiltinBuilderTest, Call_Reflect_Vector) {
auto* expr = Call("reflect", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f)); auto* expr = Call("reflect", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f));
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
{ {
@ -1019,7 +1019,7 @@ OpFunctionEnd
)"); )");
} }
TEST_F(IntrinsicBuilderTest, Call_Distance_Scalar) { TEST_F(BuiltinBuilderTest, Call_Distance_Scalar) {
auto* expr = Call("distance", 1.0f, 1.0f); auto* expr = Call("distance", 1.0f, 1.0f);
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
{ {
@ -1044,7 +1044,7 @@ OpFunctionEnd
)"); )");
} }
TEST_F(IntrinsicBuilderTest, Call_Distance_Vector) { TEST_F(BuiltinBuilderTest, Call_Distance_Vector) {
auto* expr = Call("distance", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f)); auto* expr = Call("distance", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f));
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
{ {
@ -1071,7 +1071,7 @@ OpFunctionEnd
)"); )");
} }
TEST_F(IntrinsicBuilderTest, Call_Cross) { TEST_F(BuiltinBuilderTest, Call_Cross) {
auto* expr = auto* expr =
Call("cross", vec3<f32>(1.0f, 1.0f, 1.0f), vec3<f32>(1.0f, 1.0f, 1.0f)); Call("cross", vec3<f32>(1.0f, 1.0f, 1.0f), vec3<f32>(1.0f, 1.0f, 1.0f));
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1099,9 +1099,9 @@ OpFunctionEnd
)"); )");
} }
using Intrinsic_Builtin_ThreeParam_Float_Test = using Builtin_Builtin_ThreeParam_Float_Test =
IntrinsicBuilderTestWithParam<IntrinsicData>; BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(Intrinsic_Builtin_ThreeParam_Float_Test, Call_Scalar) { TEST_P(Builtin_Builtin_ThreeParam_Float_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, 1.0f, 1.0f, 1.0f); auto* expr = Call(param.name, 1.0f, 1.0f, 1.0f);
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1128,7 +1128,7 @@ OpFunctionEnd
)"); )");
} }
TEST_P(Intrinsic_Builtin_ThreeParam_Float_Test, Call_Vector) { TEST_P(Builtin_Builtin_ThreeParam_Float_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f), auto* expr = Call(param.name, vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f),
vec2<f32>(1.0f, 1.0f)); vec2<f32>(1.0f, 1.0f));
@ -1157,16 +1157,16 @@ OpReturn
OpFunctionEnd OpFunctionEnd
)"); )");
} }
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest, INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
Intrinsic_Builtin_ThreeParam_Float_Test, Builtin_Builtin_ThreeParam_Float_Test,
testing::Values(IntrinsicData{"clamp", "NClamp"}, testing::Values(BuiltinData{"clamp", "NClamp"},
IntrinsicData{"fma", "Fma"}, BuiltinData{"fma", "Fma"},
IntrinsicData{"mix", "FMix"}, BuiltinData{"mix", "FMix"},
IntrinsicData{"smoothStep", BuiltinData{"smoothStep",
"SmoothStep"})); "SmoothStep"}));
TEST_F(IntrinsicBuilderTest, Call_FaceForward_Vector) { TEST_F(BuiltinBuilderTest, Call_FaceForward_Vector) {
auto* expr = Call("faceForward", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f), auto* expr = Call("faceForward", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f),
vec2<f32>(1.0f, 1.0f)); vec2<f32>(1.0f, 1.0f));
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1194,9 +1194,9 @@ OpFunctionEnd
)"); )");
} }
using Intrinsic_Builtin_SingleParam_Sint_Test = using Builtin_Builtin_SingleParam_Sint_Test =
IntrinsicBuilderTestWithParam<IntrinsicData>; BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(Intrinsic_Builtin_SingleParam_Sint_Test, Call_Scalar) { TEST_P(Builtin_Builtin_SingleParam_Sint_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, 1); auto* expr = Call(param.name, 1);
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1223,7 +1223,7 @@ OpFunctionEnd
)"); )");
} }
TEST_P(Intrinsic_Builtin_SingleParam_Sint_Test, Call_Vector) { TEST_P(Builtin_Builtin_SingleParam_Sint_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, vec2<i32>(1, 1)); auto* expr = Call(param.name, vec2<i32>(1, 1));
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1251,13 +1251,13 @@ OpReturn
OpFunctionEnd OpFunctionEnd
)"); )");
} }
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest, INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
Intrinsic_Builtin_SingleParam_Sint_Test, Builtin_Builtin_SingleParam_Sint_Test,
testing::Values(IntrinsicData{"abs", "SAbs"})); testing::Values(BuiltinData{"abs", "SAbs"}));
// Calling abs() on an unsigned integer scalar / vector is a no-op. // Calling abs() on an unsigned integer scalar / vector is a no-op.
using Intrinsic_Builtin_Abs_Uint_Test = IntrinsicBuilderTest; using Builtin_Builtin_Abs_Uint_Test = BuiltinBuilderTest;
TEST_F(Intrinsic_Builtin_Abs_Uint_Test, Call_Scalar) { TEST_F(Builtin_Builtin_Abs_Uint_Test, Call_Scalar) {
auto* expr = Call("abs", 1u); auto* expr = Call("abs", 1u);
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
{ {
@ -1280,7 +1280,7 @@ OpFunctionEnd
)"); )");
} }
TEST_F(Intrinsic_Builtin_Abs_Uint_Test, Call_Vector) { TEST_F(Builtin_Builtin_Abs_Uint_Test, Call_Vector) {
auto* expr = Call("abs", vec2<u32>(1u, 1u)); auto* expr = Call("abs", vec2<u32>(1u, 1u));
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
{ {
@ -1305,9 +1305,9 @@ OpFunctionEnd
)"); )");
} }
using Intrinsic_Builtin_DualParam_SInt_Test = using Builtin_Builtin_DualParam_SInt_Test =
IntrinsicBuilderTestWithParam<IntrinsicData>; BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(Intrinsic_Builtin_DualParam_SInt_Test, Call_Scalar) { TEST_P(Builtin_Builtin_DualParam_SInt_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, 1, 1); auto* expr = Call(param.name, 1, 1);
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1334,7 +1334,7 @@ OpFunctionEnd
)"); )");
} }
TEST_P(Intrinsic_Builtin_DualParam_SInt_Test, Call_Vector) { TEST_P(Builtin_Builtin_DualParam_SInt_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, vec2<i32>(1, 1), vec2<i32>(1, 1)); auto* expr = Call(param.name, vec2<i32>(1, 1), vec2<i32>(1, 1));
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1362,14 +1362,14 @@ OpReturn
OpFunctionEnd OpFunctionEnd
)"); )");
} }
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest, INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
Intrinsic_Builtin_DualParam_SInt_Test, Builtin_Builtin_DualParam_SInt_Test,
testing::Values(IntrinsicData{"max", "SMax"}, testing::Values(BuiltinData{"max", "SMax"},
IntrinsicData{"min", "SMin"})); BuiltinData{"min", "SMin"}));
using Intrinsic_Builtin_DualParam_UInt_Test = using Builtin_Builtin_DualParam_UInt_Test =
IntrinsicBuilderTestWithParam<IntrinsicData>; BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(Intrinsic_Builtin_DualParam_UInt_Test, Call_Scalar) { TEST_P(Builtin_Builtin_DualParam_UInt_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, 1u, 1u); auto* expr = Call(param.name, 1u, 1u);
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1396,7 +1396,7 @@ OpFunctionEnd
)"); )");
} }
TEST_P(Intrinsic_Builtin_DualParam_UInt_Test, Call_Vector) { TEST_P(Builtin_Builtin_DualParam_UInt_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, vec2<u32>(1u, 1u), vec2<u32>(1u, 1u)); auto* expr = Call(param.name, vec2<u32>(1u, 1u), vec2<u32>(1u, 1u));
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1424,14 +1424,14 @@ OpReturn
OpFunctionEnd OpFunctionEnd
)"); )");
} }
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest, INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
Intrinsic_Builtin_DualParam_UInt_Test, Builtin_Builtin_DualParam_UInt_Test,
testing::Values(IntrinsicData{"max", "UMax"}, testing::Values(BuiltinData{"max", "UMax"},
IntrinsicData{"min", "UMin"})); BuiltinData{"min", "UMin"}));
using Intrinsic_Builtin_ThreeParam_Sint_Test = using Builtin_Builtin_ThreeParam_Sint_Test =
IntrinsicBuilderTestWithParam<IntrinsicData>; BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(Intrinsic_Builtin_ThreeParam_Sint_Test, Call_Scalar) { TEST_P(Builtin_Builtin_ThreeParam_Sint_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, 1, 1, 1); auto* expr = Call(param.name, 1, 1, 1);
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1458,7 +1458,7 @@ OpFunctionEnd
)"); )");
} }
TEST_P(Intrinsic_Builtin_ThreeParam_Sint_Test, Call_Vector) { TEST_P(Builtin_Builtin_ThreeParam_Sint_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* expr = auto* expr =
Call(param.name, vec2<i32>(1, 1), vec2<i32>(1, 1), vec2<i32>(1, 1)); Call(param.name, vec2<i32>(1, 1), vec2<i32>(1, 1), vec2<i32>(1, 1));
@ -1487,13 +1487,13 @@ OpReturn
OpFunctionEnd OpFunctionEnd
)"); )");
} }
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest, INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
Intrinsic_Builtin_ThreeParam_Sint_Test, Builtin_Builtin_ThreeParam_Sint_Test,
testing::Values(IntrinsicData{"clamp", "SClamp"})); testing::Values(BuiltinData{"clamp", "SClamp"}));
using Intrinsic_Builtin_ThreeParam_Uint_Test = using Builtin_Builtin_ThreeParam_Uint_Test =
IntrinsicBuilderTestWithParam<IntrinsicData>; BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(Intrinsic_Builtin_ThreeParam_Uint_Test, Call_Scalar) { TEST_P(Builtin_Builtin_ThreeParam_Uint_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* expr = Call(param.name, 1u, 1u, 1u); auto* expr = Call(param.name, 1u, 1u, 1u);
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1520,7 +1520,7 @@ OpFunctionEnd
)"); )");
} }
TEST_P(Intrinsic_Builtin_ThreeParam_Uint_Test, Call_Vector) { TEST_P(Builtin_Builtin_ThreeParam_Uint_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* expr = auto* expr =
Call(param.name, vec2<u32>(1u, 1u), vec2<u32>(1u, 1u), vec2<u32>(1u, 1u)); Call(param.name, vec2<u32>(1u, 1u), vec2<u32>(1u, 1u), vec2<u32>(1u, 1u));
@ -1549,11 +1549,11 @@ OpReturn
OpFunctionEnd OpFunctionEnd
)"); )");
} }
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest, INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
Intrinsic_Builtin_ThreeParam_Uint_Test, Builtin_Builtin_ThreeParam_Uint_Test,
testing::Values(IntrinsicData{"clamp", "UClamp"})); testing::Values(BuiltinData{"clamp", "UClamp"}));
TEST_F(IntrinsicBuilderTest, Call_Modf) { TEST_F(BuiltinBuilderTest, Call_Modf) {
auto* expr = Call("modf", vec2<f32>(1.0f, 2.0f)); auto* expr = Call("modf", vec2<f32>(1.0f, 2.0f));
Func("a_func", {}, ty.void_(), {CallStmt(expr)}, Func("a_func", {}, ty.void_(), {CallStmt(expr)},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -1592,7 +1592,7 @@ OpFunctionEnd
Validate(b); Validate(b);
} }
TEST_F(IntrinsicBuilderTest, Call_Frexp) { TEST_F(BuiltinBuilderTest, Call_Frexp) {
auto* expr = Call("frexp", vec2<f32>(1.0f, 2.0f)); auto* expr = Call("frexp", vec2<f32>(1.0f, 2.0f));
Func("a_func", {}, ty.void_(), {CallStmt(expr)}, Func("a_func", {}, ty.void_(), {CallStmt(expr)},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -1633,7 +1633,7 @@ OpFunctionEnd
Validate(b); Validate(b);
} }
TEST_F(IntrinsicBuilderTest, Call_Determinant) { TEST_F(BuiltinBuilderTest, Call_Determinant) {
auto* var = Global("var", ty.mat3x3<f32>(), ast::StorageClass::kPrivate); auto* var = Global("var", ty.mat3x3<f32>(), ast::StorageClass::kPrivate);
auto* expr = Call("determinant", "var"); auto* expr = Call("determinant", "var");
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1666,7 +1666,7 @@ OpFunctionEnd
)"); )");
} }
TEST_F(IntrinsicBuilderTest, Call_Transpose) { TEST_F(BuiltinBuilderTest, Call_Transpose) {
auto* var = Global("var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate); auto* var = Global("var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate);
auto* expr = Call("transpose", "var"); auto* expr = Call("transpose", "var");
auto* func = Func("a_func", {}, ty.void_(), auto* func = Func("a_func", {}, ty.void_(),
@ -1700,7 +1700,7 @@ OpFunctionEnd
)"); )");
} }
TEST_F(IntrinsicBuilderTest, Call_ArrayLength) { TEST_F(BuiltinBuilderTest, Call_ArrayLength) {
auto* s = Structure("my_struct", {Member("a", ty.array<f32>(4))}, auto* s = Structure("my_struct", {Member("a", ty.array<f32>(4))},
{create<ast::StructBlockAttribute>()}); {create<ast::StructBlockAttribute>()});
Global("b", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, Global("b", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
@ -1745,7 +1745,7 @@ OpReturn
Validate(b); Validate(b);
} }
TEST_F(IntrinsicBuilderTest, Call_ArrayLength_OtherMembersInStruct) { TEST_F(BuiltinBuilderTest, Call_ArrayLength_OtherMembersInStruct) {
auto* s = Structure("my_struct", auto* s = Structure("my_struct",
{ {
Member("z", ty.f32()), Member("z", ty.f32()),
@ -1794,7 +1794,7 @@ OpReturn
Validate(b); Validate(b);
} }
TEST_F(IntrinsicBuilderTest, Call_ArrayLength_ViaLets) { TEST_F(BuiltinBuilderTest, Call_ArrayLength_ViaLets) {
auto* s = Structure("my_struct", {Member("a", ty.array<f32>(4))}, auto* s = Structure("my_struct", {Member("a", ty.array<f32>(4))},
{create<ast::StructBlockAttribute>()}); {create<ast::StructBlockAttribute>()});
Global("b", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, Global("b", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
@ -1844,7 +1844,7 @@ OpReturn
Validate(b); Validate(b);
} }
TEST_F(IntrinsicBuilderTest, Call_ArrayLength_ViaLets_WithPtrNoise) { TEST_F(BuiltinBuilderTest, Call_ArrayLength_ViaLets_WithPtrNoise) {
// [[block]] struct my_struct { // [[block]] struct my_struct {
// a : @stride(4) array<f32>; // a : @stride(4) array<f32>;
// }; // };
@ -1907,7 +1907,7 @@ OpReturn
Validate(b); Validate(b);
} }
TEST_F(IntrinsicBuilderTest, Call_AtomicLoad) { TEST_F(BuiltinBuilderTest, Call_AtomicLoad) {
// [[block]] struct S { // [[block]] struct S {
// u : atomic<u32>; // u : atomic<u32>;
// i : atomic<i32>; // i : atomic<i32>;
@ -1973,7 +1973,7 @@ OpReturn
Validate(b); Validate(b);
} }
TEST_F(IntrinsicBuilderTest, Call_AtomicStore) { TEST_F(BuiltinBuilderTest, Call_AtomicStore) {
// [[block]] struct S { // [[block]] struct S {
// u : atomic<u32>; // u : atomic<u32>;
// i : atomic<i32>; // i : atomic<i32>;
@ -2052,9 +2052,8 @@ OpReturn
Validate(b); Validate(b);
} }
using Intrinsic_Builtin_AtomicRMW_i32 = using Builtin_Builtin_AtomicRMW_i32 = BuiltinBuilderTestWithParam<BuiltinData>;
IntrinsicBuilderTestWithParam<IntrinsicData>; TEST_P(Builtin_Builtin_AtomicRMW_i32, Test) {
TEST_P(Intrinsic_Builtin_AtomicRMW_i32, Test) {
// [[block]] struct S { // [[block]] struct S {
// v : atomic<i32>; // v : atomic<i32>;
// } // }
@ -2121,18 +2120,17 @@ TEST_P(Intrinsic_Builtin_AtomicRMW_i32, Test) {
Validate(b); Validate(b);
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
IntrinsicBuilderTest, BuiltinBuilderTest,
Intrinsic_Builtin_AtomicRMW_i32, Builtin_Builtin_AtomicRMW_i32,
testing::Values(IntrinsicData{"atomicAdd", "OpAtomicIAdd"}, testing::Values(BuiltinData{"atomicAdd", "OpAtomicIAdd"},
IntrinsicData{"atomicMax", "OpAtomicSMax"}, BuiltinData{"atomicMax", "OpAtomicSMax"},
IntrinsicData{"atomicMin", "OpAtomicSMin"}, BuiltinData{"atomicMin", "OpAtomicSMin"},
IntrinsicData{"atomicAnd", "OpAtomicAnd"}, BuiltinData{"atomicAnd", "OpAtomicAnd"},
IntrinsicData{"atomicOr", "OpAtomicOr"}, BuiltinData{"atomicOr", "OpAtomicOr"},
IntrinsicData{"atomicXor", "OpAtomicXor"})); BuiltinData{"atomicXor", "OpAtomicXor"}));
using Intrinsic_Builtin_AtomicRMW_u32 = using Builtin_Builtin_AtomicRMW_u32 = BuiltinBuilderTestWithParam<BuiltinData>;
IntrinsicBuilderTestWithParam<IntrinsicData>; TEST_P(Builtin_Builtin_AtomicRMW_u32, Test) {
TEST_P(Intrinsic_Builtin_AtomicRMW_u32, Test) {
// [[block]] struct S { // [[block]] struct S {
// v : atomic<u32>; // v : atomic<u32>;
// } // }
@ -2198,16 +2196,16 @@ TEST_P(Intrinsic_Builtin_AtomicRMW_u32, Test) {
Validate(b); Validate(b);
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
IntrinsicBuilderTest, BuiltinBuilderTest,
Intrinsic_Builtin_AtomicRMW_u32, Builtin_Builtin_AtomicRMW_u32,
testing::Values(IntrinsicData{"atomicAdd", "OpAtomicIAdd"}, testing::Values(BuiltinData{"atomicAdd", "OpAtomicIAdd"},
IntrinsicData{"atomicMax", "OpAtomicUMax"}, BuiltinData{"atomicMax", "OpAtomicUMax"},
IntrinsicData{"atomicMin", "OpAtomicUMin"}, BuiltinData{"atomicMin", "OpAtomicUMin"},
IntrinsicData{"atomicAnd", "OpAtomicAnd"}, BuiltinData{"atomicAnd", "OpAtomicAnd"},
IntrinsicData{"atomicOr", "OpAtomicOr"}, BuiltinData{"atomicOr", "OpAtomicOr"},
IntrinsicData{"atomicXor", "OpAtomicXor"})); BuiltinData{"atomicXor", "OpAtomicXor"}));
TEST_F(IntrinsicBuilderTest, Call_AtomicExchange) { TEST_F(BuiltinBuilderTest, Call_AtomicExchange) {
// [[block]] struct S { // [[block]] struct S {
// u : atomic<u32>; // u : atomic<u32>;
// i : atomic<i32>; // i : atomic<i32>;
@ -2289,7 +2287,7 @@ OpReturn
Validate(b); Validate(b);
} }
TEST_F(IntrinsicBuilderTest, Call_AtomicCompareExchangeWeak) { TEST_F(BuiltinBuilderTest, Call_AtomicCompareExchangeWeak) {
// [[block]] struct S { // [[block]] struct S {
// u : atomic<u32>; // u : atomic<u32>;
// i : atomic<i32>; // i : atomic<i32>;
@ -2372,9 +2370,9 @@ OpReturn
Validate(b); Validate(b);
} }
using Intrinsic_Builtin_DataPacking_Test = using Builtin_Builtin_DataPacking_Test =
IntrinsicBuilderTestWithParam<IntrinsicData>; BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(Intrinsic_Builtin_DataPacking_Test, Binary) { TEST_P(Builtin_Builtin_DataPacking_Test, Binary) {
auto param = GetParam(); auto param = GetParam();
bool pack4 = param.name == "pack4x8snorm" || param.name == "pack4x8unorm"; bool pack4 = param.name == "pack4x8snorm" || param.name == "pack4x8unorm";
@ -2424,17 +2422,17 @@ OpFunctionEnd
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
IntrinsicBuilderTest, BuiltinBuilderTest,
Intrinsic_Builtin_DataPacking_Test, Builtin_Builtin_DataPacking_Test,
testing::Values(IntrinsicData{"pack4x8snorm", "PackSnorm4x8"}, testing::Values(BuiltinData{"pack4x8snorm", "PackSnorm4x8"},
IntrinsicData{"pack4x8unorm", "PackUnorm4x8"}, BuiltinData{"pack4x8unorm", "PackUnorm4x8"},
IntrinsicData{"pack2x16snorm", "PackSnorm2x16"}, BuiltinData{"pack2x16snorm", "PackSnorm2x16"},
IntrinsicData{"pack2x16unorm", "PackUnorm2x16"}, BuiltinData{"pack2x16unorm", "PackUnorm2x16"},
IntrinsicData{"pack2x16float", "PackHalf2x16"})); BuiltinData{"pack2x16float", "PackHalf2x16"}));
using Intrinsic_Builtin_DataUnpacking_Test = using Builtin_Builtin_DataUnpacking_Test =
IntrinsicBuilderTestWithParam<IntrinsicData>; BuiltinBuilderTestWithParam<BuiltinData>;
TEST_P(Intrinsic_Builtin_DataUnpacking_Test, Binary) { TEST_P(Builtin_Builtin_DataUnpacking_Test, Binary) {
auto param = GetParam(); auto param = GetParam();
bool pack4 = param.name == "unpack4x8snorm" || param.name == "unpack4x8unorm"; bool pack4 = param.name == "unpack4x8snorm" || param.name == "unpack4x8unorm";
@ -2480,15 +2478,15 @@ OpFunctionEnd
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
IntrinsicBuilderTest, BuiltinBuilderTest,
Intrinsic_Builtin_DataUnpacking_Test, Builtin_Builtin_DataUnpacking_Test,
testing::Values(IntrinsicData{"unpack4x8snorm", "UnpackSnorm4x8"}, testing::Values(BuiltinData{"unpack4x8snorm", "UnpackSnorm4x8"},
IntrinsicData{"unpack4x8unorm", "UnpackUnorm4x8"}, BuiltinData{"unpack4x8unorm", "UnpackUnorm4x8"},
IntrinsicData{"unpack2x16snorm", "UnpackSnorm2x16"}, BuiltinData{"unpack2x16snorm", "UnpackSnorm2x16"},
IntrinsicData{"unpack2x16unorm", "UnpackUnorm2x16"}, BuiltinData{"unpack2x16unorm", "UnpackUnorm2x16"},
IntrinsicData{"unpack2x16float", "UnpackHalf2x16"})); BuiltinData{"unpack2x16float", "UnpackHalf2x16"}));
TEST_F(IntrinsicBuilderTest, Call_WorkgroupBarrier) { TEST_F(BuiltinBuilderTest, Call_WorkgroupBarrier) {
Func("f", {}, ty.void_(), Func("f", {}, ty.void_(),
ast::StatementList{ ast::StatementList{
CallStmt(Call("workgroupBarrier")), CallStmt(Call("workgroupBarrier")),
@ -2522,7 +2520,7 @@ OpReturn
Validate(b); Validate(b);
} }
TEST_F(IntrinsicBuilderTest, Call_StorageBarrier) { TEST_F(BuiltinBuilderTest, Call_StorageBarrier) {
Func("f", {}, ty.void_(), Func("f", {}, ty.void_(),
ast::StatementList{ ast::StatementList{
CallStmt(Call("storageBarrier")), CallStmt(Call("storageBarrier")),

View File

@ -13,8 +13,8 @@
// limitations under the License. // limitations under the License.
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "src/ast/builtin_texture_helper_test.h"
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/intrinsic_texture_helper_test.h"
#include "src/ast/stage_attribute.h" #include "src/ast/stage_attribute.h"
#include "src/writer/spirv/spv_dump.h" #include "src/writer/spirv/spv_dump.h"
#include "src/writer/spirv/test_helper.h" #include "src/writer/spirv/test_helper.h"
@ -31,8 +31,8 @@ struct expected_texture_overload_spirv {
}; };
expected_texture_overload_spirv expected_texture_overload( expected_texture_overload_spirv expected_texture_overload(
ast::intrinsic::test::ValidTextureOverload overload) { ast::builtin::test::ValidTextureOverload overload) {
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload; using ValidTextureOverload = ast::builtin::test::ValidTextureOverload;
switch (overload) { switch (overload) {
case ValidTextureOverload::kDimensions1d: case ValidTextureOverload::kDimensions1d:
return { return {
@ -3672,15 +3672,15 @@ OpImageWrite %10 %16 %22
"<unmatched texture overload>"}; "<unmatched texture overload>"};
} // NOLINT - Ignore the length of this function } // NOLINT - Ignore the length of this function
using IntrinsicTextureTest = using BuiltinTextureTest =
TestParamHelper<ast::intrinsic::test::TextureOverloadCase>; TestParamHelper<ast::builtin::test::TextureOverloadCase>;
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
IntrinsicTextureTest, BuiltinTextureTest,
IntrinsicTextureTest, BuiltinTextureTest,
testing::ValuesIn(ast::intrinsic::test::TextureOverloadCase::ValidCases())); testing::ValuesIn(ast::builtin::test::TextureOverloadCase::ValidCases()));
TEST_P(IntrinsicTextureTest, Call) { TEST_P(BuiltinTextureTest, Call) {
auto param = GetParam(); auto param = GetParam();
auto* texture = param.BuildTextureVariable(this); auto* texture = param.BuildTextureVariable(this);
@ -3706,7 +3706,7 @@ TEST_P(IntrinsicTextureTest, Call) {
} }
// Check the SPIRV generated passes validation // Check the SPIRV generated passes validation
TEST_P(IntrinsicTextureTest, ValidateSPIRV) { TEST_P(BuiltinTextureTest, ValidateSPIRV) {
auto param = GetParam(); auto param = GetParam();
param.BuildTextureVariable(this); param.BuildTextureVariable(this);
@ -3724,11 +3724,11 @@ TEST_P(IntrinsicTextureTest, ValidateSPIRV) {
Validate(b); Validate(b);
} }
TEST_P(IntrinsicTextureTest, OutsideFunction_IsError) { TEST_P(BuiltinTextureTest, OutsideFunction_IsError) {
auto param = GetParam(); auto param = GetParam();
// The point of this test is to try to generate the texture // The point of this test is to try to generate the texture
// intrinsic call outside a function. // builtin call outside a function.
auto* texture = param.BuildTextureVariable(this); auto* texture = param.BuildTextureVariable(this);
auto* sampler = param.BuildSamplerVariable(this); auto* sampler = param.BuildSamplerVariable(this);

View File

@ -153,6 +153,8 @@ tint_unittests_source_set("tint_unittests_ast_src") {
"../src/ast/bool_test.cc", "../src/ast/bool_test.cc",
"../src/ast/break_statement_test.cc", "../src/ast/break_statement_test.cc",
"../src/ast/builtin_attribute_test.cc", "../src/ast/builtin_attribute_test.cc",
"../src/ast/builtin_texture_helper_test.cc",
"../src/ast/builtin_texture_helper_test.h",
"../src/ast/call_expression_test.cc", "../src/ast/call_expression_test.cc",
"../src/ast/call_statement_test.cc", "../src/ast/call_statement_test.cc",
"../src/ast/case_statement_test.cc", "../src/ast/case_statement_test.cc",
@ -174,8 +176,6 @@ tint_unittests_source_set("tint_unittests_ast_src") {
"../src/ast/index_accessor_expression_test.cc", "../src/ast/index_accessor_expression_test.cc",
"../src/ast/int_literal_expression_test.cc", "../src/ast/int_literal_expression_test.cc",
"../src/ast/interpolate_attribute_test.cc", "../src/ast/interpolate_attribute_test.cc",
"../src/ast/intrinsic_texture_helper_test.cc",
"../src/ast/intrinsic_texture_helper_test.h",
"../src/ast/invariant_attribute_test.cc", "../src/ast/invariant_attribute_test.cc",
"../src/ast/location_attribute_test.cc", "../src/ast/location_attribute_test.cc",
"../src/ast/loop_statement_test.cc", "../src/ast/loop_statement_test.cc",
@ -239,6 +239,8 @@ tint_unittests_source_set("tint_unittests_resolver_src") {
"../src/resolver/atomics_validation_test.cc", "../src/resolver/atomics_validation_test.cc",
"../src/resolver/bitcast_validation_test.cc", "../src/resolver/bitcast_validation_test.cc",
"../src/resolver/builtins_validation_test.cc", "../src/resolver/builtins_validation_test.cc",
"../src/resolver/builtin_test.cc",
"../src/resolver/builtin_validation_test.cc",
"../src/resolver/call_test.cc", "../src/resolver/call_test.cc",
"../src/resolver/call_validation_test.cc", "../src/resolver/call_validation_test.cc",
"../src/resolver/compound_statement_test.cc", "../src/resolver/compound_statement_test.cc",
@ -248,8 +250,6 @@ tint_unittests_source_set("tint_unittests_resolver_src") {
"../src/resolver/entry_point_validation_test.cc", "../src/resolver/entry_point_validation_test.cc",
"../src/resolver/function_validation_test.cc", "../src/resolver/function_validation_test.cc",
"../src/resolver/host_shareable_validation_test.cc", "../src/resolver/host_shareable_validation_test.cc",
"../src/resolver/intrinsic_test.cc",
"../src/resolver/intrinsic_validation_test.cc",
"../src/resolver/is_host_shareable_test.cc", "../src/resolver/is_host_shareable_test.cc",
"../src/resolver/is_storeable_test.cc", "../src/resolver/is_storeable_test.cc",
"../src/resolver/pipeline_overridable_constant_test.cc", "../src/resolver/pipeline_overridable_constant_test.cc",
@ -278,12 +278,12 @@ tint_unittests_source_set("tint_unittests_sem_src") {
sources = [ sources = [
"../src/sem/atomic_type_test.cc", "../src/sem/atomic_type_test.cc",
"../src/sem/bool_type_test.cc", "../src/sem/bool_type_test.cc",
"../src/sem/builtin_test.cc",
"../src/sem/depth_multisampled_texture_type_test.cc", "../src/sem/depth_multisampled_texture_type_test.cc",
"../src/sem/depth_texture_type_test.cc", "../src/sem/depth_texture_type_test.cc",
"../src/sem/external_texture_type_test.cc", "../src/sem/external_texture_type_test.cc",
"../src/sem/f32_type_test.cc", "../src/sem/f32_type_test.cc",
"../src/sem/i32_type_test.cc", "../src/sem/i32_type_test.cc",
"../src/sem/intrinsic_test.cc",
"../src/sem/matrix_type_test.cc", "../src/sem/matrix_type_test.cc",
"../src/sem/multisampled_texture_type_test.cc", "../src/sem/multisampled_texture_type_test.cc",
"../src/sem/pointer_type_test.cc", "../src/sem/pointer_type_test.cc",
@ -413,6 +413,8 @@ tint_unittests_source_set("tint_unittests_spv_writer_src") {
"../src/writer/spirv/builder_binary_expression_test.cc", "../src/writer/spirv/builder_binary_expression_test.cc",
"../src/writer/spirv/builder_bitcast_expression_test.cc", "../src/writer/spirv/builder_bitcast_expression_test.cc",
"../src/writer/spirv/builder_block_test.cc", "../src/writer/spirv/builder_block_test.cc",
"../src/writer/spirv/builder_builtin_test.cc",
"../src/writer/spirv/builder_builtin_texture_test.cc",
"../src/writer/spirv/builder_call_test.cc", "../src/writer/spirv/builder_call_test.cc",
"../src/writer/spirv/builder_constructor_expression_test.cc", "../src/writer/spirv/builder_constructor_expression_test.cc",
"../src/writer/spirv/builder_discard_test.cc", "../src/writer/spirv/builder_discard_test.cc",
@ -424,8 +426,6 @@ tint_unittests_source_set("tint_unittests_spv_writer_src") {
"../src/writer/spirv/builder_global_variable_test.cc", "../src/writer/spirv/builder_global_variable_test.cc",
"../src/writer/spirv/builder_ident_expression_test.cc", "../src/writer/spirv/builder_ident_expression_test.cc",
"../src/writer/spirv/builder_if_test.cc", "../src/writer/spirv/builder_if_test.cc",
"../src/writer/spirv/builder_intrinsic_test.cc",
"../src/writer/spirv/builder_intrinsic_texture_test.cc",
"../src/writer/spirv/builder_literal_test.cc", "../src/writer/spirv/builder_literal_test.cc",
"../src/writer/spirv/builder_loop_test.cc", "../src/writer/spirv/builder_loop_test.cc",
"../src/writer/spirv/builder_return_test.cc", "../src/writer/spirv/builder_return_test.cc",
@ -576,6 +576,8 @@ tint_unittests_source_set("tint_unittests_msl_writer_src") {
"../src/writer/msl/generator_impl_bitcast_test.cc", "../src/writer/msl/generator_impl_bitcast_test.cc",
"../src/writer/msl/generator_impl_block_test.cc", "../src/writer/msl/generator_impl_block_test.cc",
"../src/writer/msl/generator_impl_break_test.cc", "../src/writer/msl/generator_impl_break_test.cc",
"../src/writer/msl/generator_impl_builtin_test.cc",
"../src/writer/msl/generator_impl_builtin_texture_test.cc",
"../src/writer/msl/generator_impl_call_test.cc", "../src/writer/msl/generator_impl_call_test.cc",
"../src/writer/msl/generator_impl_case_test.cc", "../src/writer/msl/generator_impl_case_test.cc",
"../src/writer/msl/generator_impl_cast_test.cc", "../src/writer/msl/generator_impl_cast_test.cc",
@ -586,8 +588,6 @@ tint_unittests_source_set("tint_unittests_msl_writer_src") {
"../src/writer/msl/generator_impl_identifier_test.cc", "../src/writer/msl/generator_impl_identifier_test.cc",
"../src/writer/msl/generator_impl_if_test.cc", "../src/writer/msl/generator_impl_if_test.cc",
"../src/writer/msl/generator_impl_import_test.cc", "../src/writer/msl/generator_impl_import_test.cc",
"../src/writer/msl/generator_impl_intrinsic_test.cc",
"../src/writer/msl/generator_impl_intrinsic_texture_test.cc",
"../src/writer/msl/generator_impl_loop_test.cc", "../src/writer/msl/generator_impl_loop_test.cc",
"../src/writer/msl/generator_impl_member_accessor_test.cc", "../src/writer/msl/generator_impl_member_accessor_test.cc",
"../src/writer/msl/generator_impl_module_constant_test.cc", "../src/writer/msl/generator_impl_module_constant_test.cc",
@ -615,6 +615,8 @@ tint_unittests_source_set("tint_unittests_hlsl_writer_src") {
"../src/writer/hlsl/generator_impl_bitcast_test.cc", "../src/writer/hlsl/generator_impl_bitcast_test.cc",
"../src/writer/hlsl/generator_impl_block_test.cc", "../src/writer/hlsl/generator_impl_block_test.cc",
"../src/writer/hlsl/generator_impl_break_test.cc", "../src/writer/hlsl/generator_impl_break_test.cc",
"../src/writer/hlsl/generator_impl_builtin_test.cc",
"../src/writer/hlsl/generator_impl_builtin_texture_test.cc",
"../src/writer/hlsl/generator_impl_call_test.cc", "../src/writer/hlsl/generator_impl_call_test.cc",
"../src/writer/hlsl/generator_impl_case_test.cc", "../src/writer/hlsl/generator_impl_case_test.cc",
"../src/writer/hlsl/generator_impl_cast_test.cc", "../src/writer/hlsl/generator_impl_cast_test.cc",
@ -625,8 +627,6 @@ tint_unittests_source_set("tint_unittests_hlsl_writer_src") {
"../src/writer/hlsl/generator_impl_identifier_test.cc", "../src/writer/hlsl/generator_impl_identifier_test.cc",
"../src/writer/hlsl/generator_impl_if_test.cc", "../src/writer/hlsl/generator_impl_if_test.cc",
"../src/writer/hlsl/generator_impl_import_test.cc", "../src/writer/hlsl/generator_impl_import_test.cc",
"../src/writer/hlsl/generator_impl_intrinsic_test.cc",
"../src/writer/hlsl/generator_impl_intrinsic_texture_test.cc",
"../src/writer/hlsl/generator_impl_loop_test.cc", "../src/writer/hlsl/generator_impl_loop_test.cc",
"../src/writer/hlsl/generator_impl_member_accessor_test.cc", "../src/writer/hlsl/generator_impl_member_accessor_test.cc",
"../src/writer/hlsl/generator_impl_module_constant_test.cc", "../src/writer/hlsl/generator_impl_module_constant_test.cc",
@ -656,6 +656,8 @@ tint_unittests_source_set("tint_unittests_glsl_writer_src") {
"../src/writer/glsl/generator_impl_bitcast_test.cc", "../src/writer/glsl/generator_impl_bitcast_test.cc",
"../src/writer/glsl/generator_impl_block_test.cc", "../src/writer/glsl/generator_impl_block_test.cc",
"../src/writer/glsl/generator_impl_break_test.cc", "../src/writer/glsl/generator_impl_break_test.cc",
"../src/writer/glsl/generator_impl_builtin_test.cc",
"../src/writer/glsl/generator_impl_builtin_texture_test.cc",
"../src/writer/glsl/generator_impl_call_test.cc", "../src/writer/glsl/generator_impl_call_test.cc",
"../src/writer/glsl/generator_impl_case_test.cc", "../src/writer/glsl/generator_impl_case_test.cc",
"../src/writer/glsl/generator_impl_cast_test.cc", "../src/writer/glsl/generator_impl_cast_test.cc",
@ -666,8 +668,6 @@ tint_unittests_source_set("tint_unittests_glsl_writer_src") {
"../src/writer/glsl/generator_impl_identifier_test.cc", "../src/writer/glsl/generator_impl_identifier_test.cc",
"../src/writer/glsl/generator_impl_if_test.cc", "../src/writer/glsl/generator_impl_if_test.cc",
"../src/writer/glsl/generator_impl_import_test.cc", "../src/writer/glsl/generator_impl_import_test.cc",
"../src/writer/glsl/generator_impl_intrinsic_test.cc",
"../src/writer/glsl/generator_impl_intrinsic_texture_test.cc",
"../src/writer/glsl/generator_impl_loop_test.cc", "../src/writer/glsl/generator_impl_loop_test.cc",
"../src/writer/glsl/generator_impl_member_accessor_test.cc", "../src/writer/glsl/generator_impl_member_accessor_test.cc",
"../src/writer/glsl/generator_impl_module_constant_test.cc", "../src/writer/glsl/generator_impl_module_constant_test.cc",
@ -692,11 +692,11 @@ tint_unittests_source_set("tint_unittests_glsl_writer_src") {
tint_unittests_source_set("tint_unittests_core_src") { tint_unittests_source_set("tint_unittests_core_src") {
sources = [ sources = [
"../src/block_allocator_test.cc", "../src/block_allocator_test.cc",
"../src/builtin_table_test.cc",
"../src/castable_test.cc", "../src/castable_test.cc",
"../src/clone_context_test.cc", "../src/clone_context_test.cc",
"../src/debug_test.cc", "../src/debug_test.cc",
"../src/demangler_test.cc", "../src/demangler_test.cc",
"../src/intrinsic_table_test.cc",
"../src/program_builder_test.cc", "../src/program_builder_test.cc",
"../src/program_test.cc", "../src/program_test.cc",
"../src/scope_stack_test.cc", "../src/scope_stack_test.cc",

View File

@ -1,20 +1,20 @@
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:4:7 warning: use of deprecated builtin
_ = isNormal(4.); _ = isNormal(4.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:7:3 warning: use of deprecated builtin
isNormal(vec4<f32>()); isNormal(vec4<f32>());
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:10:6 warning: use of deprecated builtin
isNormal(0.); isNormal(0.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:11:9 warning: use of deprecated builtin
_ = isNormal(4.); _ = isNormal(4.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:12:9 warning: use of deprecated builtin
_ = isNormal(2.); _ = isNormal(2.);
^^^^^^^^ ^^^^^^^^

View File

@ -1,20 +1,20 @@
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:4:7 warning: use of deprecated builtin
_ = isNormal(4.); _ = isNormal(4.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:7:3 warning: use of deprecated builtin
isNormal(vec4<f32>()); isNormal(vec4<f32>());
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:10:6 warning: use of deprecated builtin
isNormal(0.); isNormal(0.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:11:9 warning: use of deprecated builtin
_ = isNormal(4.); _ = isNormal(4.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:12:9 warning: use of deprecated builtin
_ = isNormal(2.); _ = isNormal(2.);
^^^^^^^^ ^^^^^^^^

View File

@ -1,20 +1,20 @@
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:4:7 warning: use of deprecated builtin
_ = isNormal(4.); _ = isNormal(4.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:7:3 warning: use of deprecated builtin
isNormal(vec4<f32>()); isNormal(vec4<f32>());
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:10:6 warning: use of deprecated builtin
isNormal(0.); isNormal(0.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:11:9 warning: use of deprecated builtin
_ = isNormal(4.); _ = isNormal(4.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:12:9 warning: use of deprecated builtin
_ = isNormal(2.); _ = isNormal(2.);
^^^^^^^^ ^^^^^^^^

View File

@ -1,20 +1,20 @@
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:4:7 warning: use of deprecated builtin
_ = isNormal(4.); _ = isNormal(4.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:7:3 warning: use of deprecated builtin
isNormal(vec4<f32>()); isNormal(vec4<f32>());
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:10:6 warning: use of deprecated builtin
isNormal(0.); isNormal(0.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:11:9 warning: use of deprecated builtin
_ = isNormal(4.); _ = isNormal(4.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:12:9 warning: use of deprecated builtin
_ = isNormal(2.); _ = isNormal(2.);
^^^^^^^^ ^^^^^^^^

View File

@ -1,20 +1,20 @@
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:4:7 warning: use of deprecated builtin
_ = isNormal(4.); _ = isNormal(4.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:7:3 warning: use of deprecated builtin
isNormal(vec4<f32>()); isNormal(vec4<f32>());
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:10:6 warning: use of deprecated builtin
isNormal(0.); isNormal(0.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:11:9 warning: use of deprecated builtin
_ = isNormal(4.); _ = isNormal(4.);
^^^^^^^^ ^^^^^^^^
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated intrinsic bug/chromium/1273230.wgsl:12:9 warning: use of deprecated builtin
_ = isNormal(2.); _ = isNormal(2.);
^^^^^^^^ ^^^^^^^^

Some files were not shown because too many files have changed in this diff Show More