diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 77d3eebadb..9927bdde1a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -550,6 +550,8 @@ if(${TINT_BUILD_TESTS}) resolver/intrinsic_test.cc resolver/is_host_shareable_test.cc resolver/is_storeable_test.cc + resolver/ptr_ref_test.cc + resolver/ptr_ref_validation_test.cc resolver/pipeline_overridable_constant_test.cc resolver/resolver_test_helper.cc resolver/resolver_test_helper.h @@ -561,6 +563,8 @@ if(${TINT_BUILD_TESTS}) resolver/type_constructor_validation_test.cc resolver/type_validation_test.cc resolver/validation_test.cc + resolver/var_let_test.cc + resolver/var_let_validation_test.cc scope_stack_test.cc sem/intrinsic_test.cc symbol_table_test.cc diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc index eb79153fc9..b8ac9b454e 100644 --- a/src/inspector/inspector.cc +++ b/src/inspector/inspector.cc @@ -227,7 +227,7 @@ std::vector Inspector::GetEntryPoints() { stage_variable.name = name; stage_variable.component_type = ComponentType::kUnknown; - auto* type = var->Type()->UnwrapAll(); + auto* type = var->Type()->UnwrapRef(); if (type->is_float_scalar_or_vector() || type->is_float_matrix()) { stage_variable.component_type = ComponentType::kFloat; } else if (type->is_unsigned_scalar_or_vector()) { @@ -400,7 +400,7 @@ std::vector Inspector::GetUniformBufferResourceBindings( auto* var = ruv.first; auto binding_info = ruv.second; - auto* unwrapped_type = var->Type()->UnwrapAccess(); + auto* unwrapped_type = var->Type()->UnwrapRef(); auto* str = unwrapped_type->As(); if (str == nullptr) { continue; @@ -522,7 +522,7 @@ std::vector Inspector::GetDepthTextureResourceBindings( entry.bind_group = binding_info.group->value(); entry.binding = binding_info.binding->value(); - auto* texture_type = var->Type()->UnwrapAccess()->As(); + auto* texture_type = var->Type()->UnwrapRef()->As(); entry.dim = TypeTextureDimensionToResourceBindingTextureDimension( texture_type->dim()); @@ -550,7 +550,7 @@ std::vector Inspector::GetExternalTextureResourceBindings( entry.bind_group = binding_info.group->value(); entry.binding = binding_info.binding->value(); - auto* texture_type = var->Type()->UnwrapAccess()->As(); + auto* texture_type = var->Type()->UnwrapRef()->As(); entry.dim = TypeTextureDimensionToResourceBindingTextureDimension( texture_type->dim()); @@ -584,7 +584,7 @@ void Inspector::AddEntryPointInOutVariables( return; } - auto* unwrapped_type = type->UnwrapAll(); + auto* unwrapped_type = type->UnwrapRef(); if (auto* struct_ty = unwrapped_type->As()) { // Recurse into members. @@ -641,7 +641,7 @@ std::vector Inspector::GetStorageBufferResourceBindingsImpl( continue; } - auto* str = var->Type()->UnwrapAccess()->As(); + auto* str = var->Type()->UnwrapRef()->As(); if (!str) { continue; } @@ -685,7 +685,7 @@ std::vector Inspector::GetSampledTextureResourceBindingsImpl( entry.bind_group = binding_info.group->value(); entry.binding = binding_info.binding->value(); - auto* texture_type = var->Type()->UnwrapAccess()->As(); + auto* texture_type = var->Type()->UnwrapRef()->As(); entry.dim = TypeTextureDimensionToResourceBindingTextureDimension( texture_type->dim()); @@ -717,7 +717,7 @@ std::vector Inspector::GetStorageTextureResourceBindingsImpl( auto* var = ref.first; auto binding_info = ref.second; - auto* texture_type = var->Type()->As(); + auto* texture_type = var->Type()->UnwrapRef()->As(); if (read_only != (texture_type->access_control() == ast::AccessControl::kReadOnly)) { diff --git a/src/intrinsic_table.cc b/src/intrinsic_table.cc index 802034fedf..e313d0a262 100644 --- a/src/intrinsic_table.cc +++ b/src/intrinsic_table.cc @@ -1305,7 +1305,7 @@ std::string CallSignature(ProgramBuilder& builder, ss << ", "; } first = false; - ss << arg->FriendlyName(builder.Symbols()); + ss << arg->UnwrapRef()->FriendlyName(builder.Symbols()); } } ss << ")"; @@ -1391,14 +1391,7 @@ sem::Intrinsic* Impl::Overload::Match(ProgramBuilder& builder, return nullptr; } - auto* arg_ty = args[i]; - if (auto* ptr = arg_ty->As()) { - if (!parameters[i].matcher->ExpectsPointer()) { - // Argument is a pointer, but the matcher isn't expecting one. - // Perform an implicit dereference. - arg_ty = ptr->StoreType(); - } - } + auto* arg_ty = args[i]->UnwrapRef(); if (parameters[i].matcher->Match(matcher_state, arg_ty)) { // A correct parameter match is scored higher than number of parameters to // arguments. diff --git a/src/intrinsic_table_test.cc b/src/intrinsic_table_test.cc index 5bd2f5d5e6..8065f030e7 100644 --- a/src/intrinsic_table_test.cc +++ b/src/intrinsic_table_test.cc @@ -19,6 +19,7 @@ #include "src/sem/depth_texture_type.h" #include "src/sem/external_texture_type.h" #include "src/sem/multisampled_texture_type.h" +#include "src/sem/reference_type.h" #include "src/sem/sampled_texture_type.h" #include "src/sem/storage_texture_type.h" @@ -345,10 +346,11 @@ TEST_F(IntrinsicTableTest, MismatchTexture) { ASSERT_THAT(result.diagnostics.str(), HasSubstr("no matching call")); } -TEST_F(IntrinsicTableTest, MatchAutoPointerDereference) { - auto result = - table->Lookup(*this, IntrinsicType::kCos, - {ty.pointer(ast::StorageClass::kNone)}, Source{}); +TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) { + auto result = table->Lookup( + *this, IntrinsicType::kCos, + {create(create(), ast::StorageClass::kNone)}, + Source{}); ASSERT_NE(result.intrinsic, nullptr); ASSERT_EQ(result.diagnostics.str(), ""); EXPECT_THAT(result.intrinsic->Type(), IntrinsicType::kCos); diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc index 805fc56fce..c3d6b062b2 100644 --- a/src/reader/spirv/function.cc +++ b/src/reader/spirv/function.cc @@ -1088,15 +1088,15 @@ bool FunctionEmitter::ParseFunctionDeclaration(FunctionDeclaration* decl) { ast::VariableList ast_params; function_.ForEachParam( [this, &ast_params](const spvtools::opt::Instruction* param) { - auto* ast_type = parser_impl_.ConvertType(param->type_id()); - if (ast_type != nullptr) { + auto* type = parser_impl_.ConvertType(param->type_id()); + if (type != nullptr) { auto* ast_param = parser_impl_.MakeVariable( - param->result_id(), ast::StorageClass::kNone, ast_type, true, - nullptr, ast::DecorationList{}); + param->result_id(), ast::StorageClass::kNone, type, true, nullptr, + ast::DecorationList{}); // Parameters are treated as const declarations. ast_params.emplace_back(ast_param); // The value is accessible by name. - identifier_values_.insert(param->result_id()); + identifier_types_.emplace(param->result_id(), type); } else { // We've already logged an error and emitted a diagnostic. Do nothing // here. @@ -2194,8 +2194,8 @@ bool FunctionEmitter::EmitFunctionVariables() { constructor, ast::DecorationList{}); auto* var_decl_stmt = create(Source{}, var); AddStatement(var_decl_stmt); - // Save this as an already-named value. - identifier_values_.insert(inst.result_id()); + auto* var_type = ty_.Reference(var_store_type, ast::StorageClass::kNone); + identifier_types_.emplace(inst.result_id(), var_type); } return success(); } @@ -2246,7 +2246,15 @@ TypedExpression FunctionEmitter::MakeExpression(uint32_t id) { create( Source{}, builder_.Symbols().Register(name))}; } - if (identifier_values_.count(id) || parser_impl_.IsScalarSpecConstant(id)) { + auto type_it = identifier_types_.find(id); + if (type_it != identifier_types_.end()) { + auto name = namer_.Name(id); + auto* type = type_it->second; + return TypedExpression{type, + create( + Source{}, builder_.Symbols().Register(name))}; + } + if (parser_impl_.IsScalarSpecConstant(id)) { auto name = namer_.Name(id); return TypedExpression{ parser_impl_.ConvertType(def_use_mgr_->GetDef(id)->type_id()), @@ -2271,9 +2279,10 @@ TypedExpression FunctionEmitter::MakeExpression(uint32_t id) { case SpvOpVariable: { // This occurs for module-scope variables. auto name = namer_.Name(inst->result_id()); - return TypedExpression{parser_impl_.ConvertType(inst->type_id()), - create( - Source{}, builder_.Symbols().Register(name))}; + return TypedExpression{ + parser_impl_.ConvertType(inst->type_id(), PtrAs::Ref), + create(Source{}, + builder_.Symbols().Register(name))}; } case SpvOpUndef: // Substitute a null value for undef. @@ -2624,7 +2633,7 @@ bool FunctionEmitter::EmitIfStart(const BlockInfo& block_info) { // just like in the original SPIR-V. PushTrueGuard(construct->end_id); } else { - // Add a flow guard around the blocks in the premege area. + // Add a flow guard around the blocks in the premerge area. PushGuard(guard_name, construct->end_id); } } @@ -2836,7 +2845,7 @@ bool FunctionEmitter::EmitNormalTerminator(const BlockInfo& block_info) { const auto true_dest = terminator.GetSingleWordInOperand(1); const auto false_dest = terminator.GetSingleWordInOperand(2); if (true_dest == false_dest) { - // This is like an uncondtional branch. + // This is like an unconditional branch. AddStatement(MakeBranch(block_info, *GetBlockInfo(true_dest))); return true; } @@ -3064,14 +3073,14 @@ bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info, for (auto id : sorted_by_index(block_info.hoisted_ids)) { const auto* def_inst = def_use_mgr_->GetDef(id); TINT_ASSERT(def_inst); - auto* ast_type = + auto* storage_type = RemapStorageClass(parser_impl_.ConvertType(def_inst->type_id()), id); AddStatement(create( Source{}, - parser_impl_.MakeVariable(id, ast::StorageClass::kNone, ast_type, false, - nullptr, ast::DecorationList{}))); - // Save this as an already-named value. - identifier_values_.insert(id); + parser_impl_.MakeVariable(id, ast::StorageClass::kNone, storage_type, + false, nullptr, ast::DecorationList{}))); + auto* type = ty_.Reference(storage_type, ast::StorageClass::kNone); + identifier_types_.emplace(id, type); } // Emit declarations of phi state variables, in index order. for (auto id : sorted_by_index(block_info.phis_needing_state_vars)) { @@ -3131,25 +3140,29 @@ bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info, bool FunctionEmitter::EmitConstDefinition( const spvtools::opt::Instruction& inst, - TypedExpression ast_expr) { - if (!ast_expr) { + TypedExpression expr) { + if (!expr) { return false; } + if (expr.type->Is()) { + // `let` declarations cannot hold references, so we need to take the address + // of the RHS, and make the `let` be a pointer. + expr = AddressOf(expr); + } auto* ast_const = parser_impl_.MakeVariable( - inst.result_id(), ast::StorageClass::kNone, ast_expr.type, true, - ast_expr.expr, ast::DecorationList{}); + inst.result_id(), ast::StorageClass::kNone, expr.type, true, expr.expr, + ast::DecorationList{}); if (!ast_const) { return false; } AddStatement(create(Source{}, ast_const)); - // Save this as an already-named value. - identifier_values_.insert(inst.result_id()); + identifier_types_.emplace(inst.result_id(), expr.type); return success(); } bool FunctionEmitter::EmitConstDefOrWriteToHoistedVar( const spvtools::opt::Instruction& inst, - TypedExpression ast_expr) { + TypedExpression expr) { const auto result_id = inst.result_id(); const auto* def_info = GetDefInfo(result_id); if (def_info && def_info->requires_hoisted_def) { @@ -3159,10 +3172,10 @@ bool FunctionEmitter::EmitConstDefOrWriteToHoistedVar( Source{}, create(Source{}, builder_.Symbols().Register(name)), - ast_expr.expr)); + expr.expr)); return true; } - return EmitConstDefinition(inst, ast_expr); + return EmitConstDefinition(inst, expr); } bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) { @@ -3283,6 +3296,12 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) { return false; } + if (lhs.type->Is()) { + // LHS of an assignment must be a reference type. + // Convert the LHS to a reference by dereferencing it. + lhs = Dereference(lhs); + } + AddStatement( create(Source{}, lhs.expr, rhs.expr)); return success(); @@ -3343,16 +3362,21 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) { return false; } - // The load result type is the pointee type of its operand. - TINT_ASSERT(expr.type->Is()); - expr.type = expr.type->As()->type; + // The load result type is the storage type of its operand. + if (expr.type->Is()) { + expr = Dereference(expr); + } else if (auto* ref = expr.type->As()) { + expr.type = ref->type; + } else { + Fail() << "OpLoad expression is not a pointer or reference"; + return false; + } + return EmitConstDefOrWriteToHoistedVar(inst, expr); } case SpvOpCopyMemory: { // Generate an assignment. - // TODO(dneto): When supporting ptr-ref, the LHS pointer and RHS pointer - // map to reference types in WGSL. auto lhs = MakeOperand(inst, 0); auto rhs = MakeOperand(inst, 1); // Ignore any potential memory operands. Currently they are all for @@ -3367,6 +3391,15 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) { if (!success()) { return false; } + + // LHS and RHS pointers must be reference types in WGSL. + if (lhs.type->Is()) { + lhs = Dereference(lhs); + } + if (rhs.type->Is()) { + rhs = Dereference(rhs); + } + AddStatement( create(Source{}, lhs.expr, rhs.expr)); return success(); @@ -3386,6 +3419,11 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) { if (!expr) { return false; } + if (expr.type->Is()) { + // If the source is a reference, then we need to take the address of the + // expression. + expr = AddressOf(expr); + } expr.type = RemapStorageClass(expr.type, result_id); return EmitConstDefOrWriteToHoistedVar(inst, expr); } @@ -3782,7 +3820,7 @@ TypedExpression FunctionEmitter::MakeAccessChain( auto name = namer_.Name(base_id); current_expr.expr = create( Source{}, builder_.Symbols().Register(name)); - current_expr.type = parser_impl_.ConvertType(ptr_ty_id); + current_expr.type = parser_impl_.ConvertType(ptr_ty_id, PtrAs::Ref); } } @@ -3898,10 +3936,9 @@ TypedExpression FunctionEmitter::MakeAccessChain( } const auto pointer_type_id = type_mgr_->FindPointerToType(pointee_type_id, storage_class); - auto* ast_pointer_type = parser_impl_.ConvertType(pointer_type_id); - TINT_ASSERT(ast_pointer_type); - TINT_ASSERT(ast_pointer_type->Is()); - current_expr = TypedExpression{ast_pointer_type, next_expr}; + auto* type = parser_impl_.ConvertType(pointer_type_id, PtrAs::Ref); + TINT_ASSERT(type && type->Is()); + current_expr = TypedExpression{type, next_expr}; } return current_expr; } @@ -3932,7 +3969,7 @@ TypedExpression FunctionEmitter::MakeCompositeValueDecomposition( // A SPIR-V composite extract is a single instruction with multiple // literal indices walking down into composites. // A SPIR-V composite insert is similar but also tells you what component - // to inject. This function is respnosible for the the walking-into part + // to inject. This function is responsible for the the walking-into part // of composite-insert. // // The Tint AST represents this as ever-deeper nested indexing expressions. @@ -4476,15 +4513,24 @@ bool FunctionEmitter::EmitFunctionCall(const spvtools::opt::Instruction& inst) { auto* function = create( Source{}, builder_.Symbols().Register(name)); - ast::ExpressionList params; + ast::ExpressionList args; for (uint32_t iarg = 1; iarg < inst.NumInOperands(); ++iarg) { - params.emplace_back(MakeOperand(inst, iarg).expr); + auto expr = MakeOperand(inst, iarg); + if (!expr) { + return false; + } + if (expr.type->Is()) { + // Functions cannot use references as parameters, so we need to pass by + // pointer. + expr = AddressOf(expr); + } + args.emplace_back(expr.expr); } if (failed()) { return false; } auto* call_expr = - create(Source{}, function, std::move(params)); + create(Source{}, function, std::move(args)); auto* result_type = parser_impl_.ConvertType(inst.type_id()); if (!result_type) { return Fail() << "internal error: no mapped type result of call: " @@ -5394,6 +5440,32 @@ bool FunctionEmitter::MakeCompositeInsert( {ast_type, create(registered_temp_name)}); } +TypedExpression FunctionEmitter::AddressOf(TypedExpression expr) { + auto* ref = expr.type->As(); + if (!ref) { + Fail() << "AddressOf() called on non-reference type"; + return {}; + } + return { + ty_.Pointer(ref->type, ref->storage_class), + create(Source{}, ast::UnaryOp::kAddressOf, + expr.expr), + }; +} + +TypedExpression FunctionEmitter::Dereference(TypedExpression expr) { + auto* ptr = expr.type->As(); + if (!ptr) { + Fail() << "Dereference() called on non-pointer type"; + return {}; + } + return { + ptr->type, + create(Source{}, ast::UnaryOp::kIndirection, + expr.expr), + }; +} + FunctionEmitter::FunctionDeclaration::FunctionDeclaration() = default; FunctionEmitter::FunctionDeclaration::~FunctionDeclaration() = default; diff --git a/src/reader/spirv/function.h b/src/reader/spirv/function.h index edff9079ef..940e84a312 100644 --- a/src/reader/spirv/function.h +++ b/src/reader/spirv/function.h @@ -1127,6 +1127,16 @@ class FunctionEmitter { /// @returns a boolean false expression. ast::Expression* MakeFalse(const Source&) const; + /// @param expr the expression to take the address of + /// @returns a TypedExpression that is the address-of `expr` (`&expr`) + /// @note `expr` must be a reference type + TypedExpression AddressOf(TypedExpression expr); + + /// @param expr the expression to dereference + /// @returns a TypedExpression that is the dereference-of `expr` (`*expr`) + /// @note `expr` must be a pointer type + TypedExpression Dereference(TypedExpression expr); + /// Creates a new `ast::Node` owned by the ProgramBuilder. /// @param args the arguments to pass to the type constructor /// @returns the node pointer @@ -1136,6 +1146,7 @@ class FunctionEmitter { } using StatementsStack = std::vector; + using PtrAs = ParserImpl::PtrAs; ParserImpl& parser_impl_; TypeManager& ty_; @@ -1160,8 +1171,9 @@ class FunctionEmitter { // lifetime of the EmitFunctionBodyStatements method. StatementsStack statements_stack_; - // The set of IDs that have already had an identifier name generated for it. - std::unordered_set identifier_values_; + // The map of IDs that have already had an identifier name generated for it, + // to their Type. + std::unordered_map identifier_types_; // Mapping from SPIR-V ID that is used at most once, to its AST expression. std::unordered_map singly_used_values_; diff --git a/src/reader/spirv/function_composite_test.cc b/src/reader/spirv/function_composite_test.cc index 2724fd56e7..4fd0f0755a 100644 --- a/src/reader/spirv/function_composite_test.cc +++ b/src/reader/spirv/function_composite_test.cc @@ -923,7 +923,7 @@ VariableDeclStatement{ VariableConst{ x_1 none - __type_name_S_1 + __type_name_S_2 { Identifier[not set]{x_40} } @@ -1178,7 +1178,10 @@ TEST_F(SpvParserTest_CopyObject, Pointer) { none __ptr_function__u32 { - Identifier[not set]{x_10} + UnaryOp[not set]{ + address-of + Identifier[not set]{x_10} + } } } } diff --git a/src/reader/spirv/function_memory_test.cc b/src/reader/spirv/function_memory_test.cc index e6b1d3e7a3..f44846aede 100644 --- a/src/reader/spirv/function_memory_test.cc +++ b/src/reader/spirv/function_memory_test.cc @@ -1019,18 +1019,24 @@ TEST_F(SpvParserMemoryTest, none __ptr_storage__u32 { - ArrayAccessor[not set]{ - MemberAccessor[not set]{ - Identifier[not set]{myvar} - Identifier[not set]{field1} + UnaryOp[not set]{ + address-of + ArrayAccessor[not set]{ + MemberAccessor[not set]{ + Identifier[not set]{myvar} + Identifier[not set]{field1} + } + ScalarConstructor[not set]{1u} } - ScalarConstructor[not set]{1u} } } } } Assignment{ - Identifier[not set]{x_2} + UnaryOp[not set]{ + indirection + Identifier[not set]{x_2} + } ScalarConstructor[not set]{0u} })")) << p->error(); } @@ -1082,12 +1088,15 @@ If{ { Assignment{ Identifier[not set]{x_2} - ArrayAccessor[not set]{ - MemberAccessor[not set]{ - Identifier[not set]{myvar} - Identifier[not set]{field1} + UnaryOp[not set]{ + address-of + ArrayAccessor[not set]{ + MemberAccessor[not set]{ + Identifier[not set]{myvar} + Identifier[not set]{field1} + } + ScalarConstructor[not set]{1u} } - ScalarConstructor[not set]{1u} } } } diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc index 7f3ae37553..986ca7af48 100644 --- a/src/reader/spirv/parser_impl.cc +++ b/src/reader/spirv/parser_impl.cc @@ -24,6 +24,7 @@ #include "src/ast/override_decoration.h" #include "src/ast/struct_block_decoration.h" #include "src/ast/type_name.h" +#include "src/ast/unary_op_expression.h" #include "src/reader/spirv/function.h" #include "src/sem/depth_texture_type.h" #include "src/sem/multisampled_texture_type.h" @@ -304,7 +305,7 @@ Program ParserImpl::program() { return tint::Program(std::move(builder_)); } -const Type* ParserImpl::ConvertType(uint32_t type_id) { +const Type* ParserImpl::ConvertType(uint32_t type_id, PtrAs ptr_as) { if (!success_) { return nullptr; } @@ -349,7 +350,7 @@ const Type* ParserImpl::ConvertType(uint32_t type_id) { return maybe_generate_alias(ConvertType(type_id, spirv_type->AsStruct())); case spvtools::opt::analysis::Type::kPointer: return maybe_generate_alias( - ConvertType(type_id, spirv_type->AsPointer())); + ConvertType(type_id, ptr_as, spirv_type->AsPointer())); case spvtools::opt::analysis::Type::kFunction: // Tint doesn't have a Function type. // We need to convert the result type and parameter types. @@ -1041,6 +1042,7 @@ void ParserImpl::AddConstructedType(Symbol name, ast::NamedType* type) { } const Type* ParserImpl::ConvertType(uint32_t type_id, + PtrAs ptr_as, const spvtools::opt::analysis::Pointer*) { const auto* inst = def_use_mgr_->GetDef(type_id); const auto pointee_type_id = inst->GetSingleWordInOperand(1); @@ -1051,7 +1053,7 @@ const Type* ParserImpl::ConvertType(uint32_t type_id, builtin_position_.storage_class = storage_class; return nullptr; } - auto* ast_elem_ty = ConvertType(pointee_type_id); + auto* ast_elem_ty = ConvertType(pointee_type_id, PtrAs::Ptr); if (ast_elem_ty == nullptr) { Fail() << "SPIR-V pointer type with ID " << type_id << " has invalid pointee type " << pointee_type_id; @@ -1079,8 +1081,14 @@ const Type* ParserImpl::ConvertType(uint32_t type_id, ast_storage_class = ast::StorageClass::kPrivate; } } - - return ty_.Pointer(ast_elem_ty, ast_storage_class); + switch (ptr_as) { + case PtrAs::Ref: + return ty_.Reference(ast_elem_ty, ast_storage_class); + case PtrAs::Ptr: + return ty_.Pointer(ast_elem_ty, ast_storage_class); + } + Fail() << "invalid value for ptr_as: " << static_cast(ptr_as); + return nullptr; } bool ParserImpl::RegisterTypes() { @@ -1094,7 +1102,7 @@ bool ParserImpl::RegisterTypes() { } ConvertType(type_or_const.result_id()); } - // Manufacture a type for the gl_Position varible if we have to. + // Manufacture a type for the gl_Position variable if we have to. if ((builtin_position_.struct_type_id != 0) && (builtin_position_.position_member_pointer_type_id == 0)) { builtin_position_.position_member_pointer_type_id = @@ -1337,25 +1345,25 @@ const spvtools::opt::analysis::IntConstant* ParserImpl::GetArraySize( ast::Variable* ParserImpl::MakeVariable(uint32_t id, ast::StorageClass sc, - const Type* type, + const Type* storage_type, bool is_const, ast::Expression* constructor, ast::DecorationList decorations) { - if (type == nullptr) { + if (storage_type == nullptr) { Fail() << "internal error: can't make ast::Variable for null type"; return nullptr; } if (sc == ast::StorageClass::kStorage) { bool read_only = false; - if (auto* tn = type->As()) { + if (auto* tn = storage_type->As()) { read_only = read_only_struct_types_.count(tn->name) > 0; } // Apply the access(read) or access(read_write) modifier. auto access = read_only ? ast::AccessControl::kReadOnly : ast::AccessControl::kReadWrite; - type = ty_.AccessControl(type, access); + storage_type = ty_.AccessControl(storage_type, access); } // Handle variables (textures and samplers) are always in the handle @@ -1367,15 +1375,20 @@ ast::Variable* ParserImpl::MakeVariable(uint32_t id, // In almost all cases, copy the decorations from SPIR-V to the variable. // But avoid doing so when converting pipeline IO to private variables. if (sc != ast::StorageClass::kPrivate) { - if (!ConvertDecorationsForVariable(id, &type, &decorations)) { + if (!ConvertDecorationsForVariable(id, &storage_type, &decorations)) { return nullptr; } } std::string name = namer_.Name(id); + + // Note: we're constructing the variable here with the *storage* type, + // regardless of whether this is a `let` or `var` declaration. + // `var` declarations will have a resolved type of ref, but at the + // AST level both `var` and `let` are declared with the same type. return create(Source{}, builder_.Symbols().Register(name), sc, - type->Build(builder_), is_const, constructor, - decorations); + storage_type->Build(builder_), is_const, + constructor, decorations); } bool ParserImpl::ConvertDecorationsForVariable( diff --git a/src/reader/spirv/parser_impl.h b/src/reader/spirv/parser_impl.h index 9f3e336778..14250fc9f0 100644 --- a/src/reader/spirv/parser_impl.h +++ b/src/reader/spirv/parser_impl.h @@ -153,6 +153,14 @@ class ParserImpl : Reader { return glsl_std_450_imports_; } + /// Desired handling of SPIR-V pointers by ConvertType() + enum class PtrAs { + // SPIR-V pointer is converted to a spirv::Pointer + Ptr, + // SPIR-V pointer is converted to a spirv::Reference + Ref + }; + /// Converts a SPIR-V type to a Tint type, and saves it for fast lookup. /// If the type is only used for builtins, then register that specially, /// and return null. If the type is a sampler, image, or sampled image, then @@ -161,8 +169,11 @@ class ParserImpl : Reader { /// On failure, logs an error and returns null. This should only be called /// after the internal representation of the module has been built. /// @param type_id the SPIR-V ID of a type. + /// @param ptr_as if the SPIR-V type is a pointer and ptr_as is equal to + /// PtrAs::Ref then a Reference will be returned, otherwise a Pointer will be + /// returned for a SPIR-V pointer /// @returns a Tint type, or nullptr - const Type* ConvertType(uint32_t type_id); + const Type* ConvertType(uint32_t type_id, PtrAs ptr_as = PtrAs::Ptr); /// Emits an alias type declaration for the given type, if necessary, and /// also updates the mapping of the SPIR-V type ID to the alias type. @@ -339,7 +350,7 @@ class ParserImpl : Reader { /// decorations, unless it's an ignorable builtin variable. /// @param id the SPIR-V result ID /// @param sc the storage class, which cannot be ast::StorageClass::kNone - /// @param type the type + /// @param storage_type the storage type of the variable /// @param is_const if true, the variable is const /// @param constructor the variable constructor /// @param decorations the variable decorations @@ -347,7 +358,7 @@ class ParserImpl : Reader { /// in the error case ast::Variable* MakeVariable(uint32_t id, ast::StorageClass sc, - const Type* type, + const Type* storage_type, bool is_const, ast::Expression* constructor, ast::DecorationList decorations); @@ -616,12 +627,15 @@ class ParserImpl : Reader { /// @param struct_ty the Tint type const Type* ConvertType(uint32_t type_id, const spvtools::opt::analysis::Struct* struct_ty); - /// Converts a specific SPIR-V type to a Tint type. Pointer case + /// Converts a specific SPIR-V type to a Tint type. Pointer / Reference case /// The pointer to gl_PerVertex maps to nullptr, and instead is recorded /// in member #builtin_position_. /// @param type_id the SPIR-V ID for the type. + /// @param ptr_as if PtrAs::Ref then a Reference will be returned, otherwise + /// Pointer /// @param ptr_ty the Tint type const Type* ConvertType(uint32_t type_id, + PtrAs ptr_as, const spvtools::opt::analysis::Pointer* ptr_ty); /// If `type` is a signed integral, or vector of signed integral, diff --git a/src/reader/spirv/parser_impl_module_var_test.cc b/src/reader/spirv/parser_impl_module_var_test.cc index 97d2aeda13..78998962e8 100644 --- a/src/reader/spirv/parser_impl_module_var_test.cc +++ b/src/reader/spirv/parser_impl_module_var_test.cc @@ -2413,7 +2413,10 @@ TEST_F(SpvModuleScopeVarParserTest, SampleId_U32_Load_CopyObject) { none __ptr_in__u32 { - Identifier[not set]{x_1} + UnaryOp[not set]{ + address-of + Identifier[not set]{x_1} + } } } } @@ -2423,7 +2426,10 @@ TEST_F(SpvModuleScopeVarParserTest, SampleId_U32_Load_CopyObject) { none __u32 { - Identifier[not set]{x_11} + UnaryOp[not set]{ + indirection + Identifier[not set]{x_11} + } } } })")) @@ -3295,7 +3301,10 @@ TEST_F(SpvModuleScopeVarParserTest, VertexIndex_U32_Load_CopyObject) { none __ptr_in__u32 { - Identifier[not set]{x_1} + UnaryOp[not set]{ + address-of + Identifier[not set]{x_1} + } } } } @@ -3305,7 +3314,10 @@ TEST_F(SpvModuleScopeVarParserTest, VertexIndex_U32_Load_CopyObject) { none __u32 { - Identifier[not set]{x_11} + UnaryOp[not set]{ + indirection + Identifier[not set]{x_11} + } } } })")) @@ -3614,7 +3626,10 @@ TEST_F(SpvModuleScopeVarParserTest, InstanceIndex_U32_Load_CopyObject) { none __ptr_in__u32 { - Identifier[not set]{x_1} + UnaryOp[not set]{ + address-of + Identifier[not set]{x_1} + } } } } @@ -3624,7 +3639,10 @@ TEST_F(SpvModuleScopeVarParserTest, InstanceIndex_U32_Load_CopyObject) { none __u32 { - Identifier[not set]{x_11} + UnaryOp[not set]{ + indirection + Identifier[not set]{x_11} + } } } })")) diff --git a/src/resolver/assignment_validation_test.cc b/src/resolver/assignment_validation_test.cc index 1c5e69661a..86a92c23a7 100644 --- a/src/resolver/assignment_validation_test.cc +++ b/src/resolver/assignment_validation_test.cc @@ -31,39 +31,13 @@ TEST_F(ResolverAssignmentValidationTest, AssignIncompatibleTypes) { // } auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)); - auto* lhs = Expr("a"); - auto* rhs = Expr(2.3f); - auto* assign = Assign(Source{{12, 34}}, lhs, rhs); + auto* assign = Assign(Source{{12, 34}}, "a", 2.3f); WrapInFunction(var, assign); ASSERT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - R"(12:34 error: invalid assignment: cannot assign value of type 'f32' to a variable of type 'i32')"); -} - -TEST_F(ResolverAssignmentValidationTest, - AssignThroughPointerWrongeStoreType_Fail) { - // var a : f32; - // let b : ptr = a; - // b = 2; - const auto priv = ast::StorageClass::kFunction; - auto* var_a = Var("a", ty.f32(), priv); - auto* var_b = Const("b", ty.pointer(priv), Expr("a"), {}); - - auto* lhs = Expr("a"); - auto* rhs = Expr(2); - - auto* assign = Assign(Source{{12, 34}}, lhs, rhs); - WrapInFunction(var_a, var_b, assign); - - ASSERT_FALSE(r()->Resolve()); - - EXPECT_EQ( - r()->error(), - R"(12:34 error: invalid assignment: cannot assign value of type 'i32' to a variable of type 'f32')"); + EXPECT_EQ(r()->error(), "12:34 error: cannot assign 'f32' to 'i32'"); } TEST_F(ResolverAssignmentValidationTest, @@ -73,11 +47,7 @@ TEST_F(ResolverAssignmentValidationTest, // a = 2 // } auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)); - auto* lhs = Expr("a"); - auto* rhs = Expr(2); - - auto* body = Block(Decl(var), Assign(Source{{12, 34}}, lhs, rhs)); - WrapInFunction(body); + WrapInFunction(var, Assign("a", 2)); ASSERT_TRUE(r()->Resolve()) << r()->error(); } @@ -90,17 +60,11 @@ TEST_F(ResolverAssignmentValidationTest, // } auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)); - auto* lhs = Expr("a"); - auto* rhs = Expr(2.3f); - - auto* block = Block(Decl(var), Assign(Source{{12, 34}}, lhs, rhs)); - WrapInFunction(block); + WrapInFunction(var, Assign(Source{{12, 34}}, "a", 2.3f)); ASSERT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - R"(12:34 error: invalid assignment: cannot assign value of type 'f32' to a variable of type 'i32')"); + EXPECT_EQ(r()->error(), "12:34 error: cannot assign 'f32' to 'i32'"); } TEST_F(ResolverAssignmentValidationTest, @@ -113,20 +77,13 @@ TEST_F(ResolverAssignmentValidationTest, // } auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)); - auto* lhs = Expr("a"); - auto* rhs = Expr(2.3f); - - auto* inner_block = Block(Decl(var), Assign(Source{{12, 34}}, lhs, rhs)); - + auto* inner_block = Block(Decl(var), Assign(Source{{12, 34}}, "a", 2.3f)); auto* outer_block = Block(inner_block); - WrapInFunction(outer_block); ASSERT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - R"(12:34 error: invalid assignment: cannot assign value of type 'f32' to a variable of type 'i32')"); + EXPECT_EQ(r()->error(), "12:34 error: cannot assign 'f32' to 'i32'"); } TEST_F(ResolverAssignmentValidationTest, AssignToScalar_Fail) { @@ -134,28 +91,17 @@ TEST_F(ResolverAssignmentValidationTest, AssignToScalar_Fail) { // 1 = my_var; auto* var = Var("my_var", ty.i32(), ast::StorageClass::kNone, Expr(2)); - auto* lhs = Expr(1); - auto* rhs = Expr("my_var"); - - auto* assign = Assign(Source{{12, 34}}, lhs, rhs); - WrapInFunction(Decl(var), assign); + WrapInFunction(var, Assign(Expr(Source{{12, 34}}, 1), "my_var")); EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error v-000x: invalid assignment: left-hand-side does not " - "reference storage: i32"); + EXPECT_EQ(r()->error(), "12:34 error: cannot assign to value of type 'i32'"); } TEST_F(ResolverAssignmentValidationTest, AssignCompatibleTypes_Pass) { - // var a :i32 = 2; + // var a : i32 = 2; // a = 2 auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)); - - auto* lhs = Expr("a"); - auto* rhs = Expr(2); - - auto* assign = Assign(Source{Source::Location{12, 34}}, lhs, rhs); - WrapInFunction(Decl(var), assign); + WrapInFunction(var, Assign(Source{{12, 34}}, "a", 2)); EXPECT_TRUE(r()->Resolve()) << r()->error(); } @@ -163,17 +109,12 @@ TEST_F(ResolverAssignmentValidationTest, AssignCompatibleTypes_Pass) { TEST_F(ResolverAssignmentValidationTest, AssignCompatibleTypesThroughAlias_Pass) { // alias myint = i32; - // var a :myint = 2; + // var a : myint = 2; // a = 2 auto* myint = ty.alias("myint", ty.i32()); AST().AddConstructedType(myint); auto* var = Var("a", myint, ast::StorageClass::kNone, Expr(2)); - - auto* lhs = Expr("a"); - auto* rhs = Expr(2); - - auto* assign = Assign(Source{Source::Location{12, 34}}, lhs, rhs); - WrapInFunction(Decl(var), assign); + WrapInFunction(var, Assign(Source{{12, 34}}, "a", 2)); EXPECT_TRUE(r()->Resolve()) << r()->error(); } @@ -185,29 +126,19 @@ TEST_F(ResolverAssignmentValidationTest, // a = b; auto* var_a = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)); auto* var_b = Var("b", ty.i32(), ast::StorageClass::kNone, Expr(3)); - - auto* lhs = Expr("a"); - auto* rhs = Expr("b"); - - auto* assign = Assign(Source{Source::Location{12, 34}}, lhs, rhs); - WrapInFunction(Decl(var_a), Decl(var_b), assign); + WrapInFunction(var_a, var_b, Assign(Source{{12, 34}}, "a", "b")); EXPECT_TRUE(r()->Resolve()) << r()->error(); } TEST_F(ResolverAssignmentValidationTest, AssignThroughPointer_Pass) { - // var a :i32; - // let b : ptr = a; - // b = 2; + // var a : i32; + // let b : ptr = &a; + // *b = 2; const auto func = ast::StorageClass::kFunction; auto* var_a = Var("a", ty.i32(), func, Expr(2), {}); - auto* var_b = Const("b", ty.pointer(func), Expr("a"), {}); - - auto* lhs = Expr("b"); - auto* rhs = Expr(2); - - auto* assign = Assign(Source{Source::Location{12, 34}}, lhs, rhs); - WrapInFunction(Decl(var_a), Decl(var_b), assign); + auto* var_b = Const("b", ty.pointer(func), AddressOf(Expr("a")), {}); + WrapInFunction(var_a, var_b, Assign(Source{{12, 34}}, Deref("b"), 2)); EXPECT_TRUE(r()->Resolve()) << r()->error(); } @@ -218,21 +149,13 @@ TEST_F(ResolverAssignmentValidationTest, AssignToConstant_Fail) { // a = 2 // } auto* var = Const("a", ty.i32(), Expr(2)); - - auto* lhs = Expr("a"); - auto* rhs = Expr(2); - - auto* body = - Block(Decl(var), Assign(Source{Source::Location{12, 34}}, lhs, rhs)); - - WrapInFunction(body); + WrapInFunction(var, Assign(Expr(Source{{12, 34}}, "a"), 2)); EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error v-0021: cannot re-assign a constant: 'a'"); + EXPECT_EQ(r()->error(), "12:34 error: cannot assign to value of type 'i32'"); } -TEST_F(ResolverAssignmentValidationTest, AssignFromPointer_Fail) { +TEST_F(ResolverAssignmentValidationTest, AssignNonStorable_Fail) { // var a : [[access(read)]] texture_storage_1d; // var b : [[access(read)]] texture_storage_1d; // a = b; @@ -243,24 +166,23 @@ TEST_F(ResolverAssignmentValidationTest, AssignFromPointer_Fail) { return ty.access(ast::AccessControl::kReadOnly, tex_type); }; - auto* var_a = Global("a", make_type(), ast::StorageClass::kNone, nullptr, - { - create(0), - create(0), - }); - auto* var_b = Global("b", make_type(), ast::StorageClass::kNone, nullptr, - { - create(1), - create(0), - }); + Global("a", make_type(), ast::StorageClass::kNone, nullptr, + { + create(0), + create(0), + }); + Global("b", make_type(), ast::StorageClass::kNone, nullptr, + { + create(1), + create(0), + }); - WrapInFunction(Assign(Source{{12, 34}}, var_a, var_b)); + WrapInFunction(Assign("a", Expr(Source{{12, 34}}, "b"))); EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error v-000x: invalid assignment: right-hand-side is not " - "storable: ptr>"); + EXPECT_EQ( + r()->error(), + R"(12:34 error: '[[access(read)]] texture_storage_1d' is not storable)"); } } // namespace diff --git a/src/resolver/builtins_validation_test.cc b/src/resolver/builtins_validation_test.cc index 363b35a61e..fe2b59dba4 100644 --- a/src/resolver/builtins_validation_test.cc +++ b/src/resolver/builtins_validation_test.cc @@ -108,7 +108,7 @@ TEST_F(ResolverBuiltinsValidationTest, Determinant_Mat4x4) { TEST_F(ResolverBuiltinsValidationTest, Frexp_Scalar) { auto* a = Var("a", ty.i32()); - auto* builtin = Call("frexp", 1.0f, Expr("a")); + auto* builtin = Call("frexp", 1.0f, AddressOf(Expr("a"))); WrapInFunction(Decl(a), builtin); EXPECT_TRUE(r()->Resolve()) << r()->error(); @@ -118,10 +118,8 @@ TEST_F(ResolverBuiltinsValidationTest, Frexp_Scalar) { TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec2) { auto* a = Var("a", ty.vec2()); - auto* b = Const("b", ty.pointer(ty.vec2(), ast::StorageClass::kFunction), - Expr("a"), {}); - auto* builtin = Call("frexp", vec2(1.0f, 1.0f), Expr("b")); - WrapInFunction(Decl(a), Decl(b), builtin); + auto* builtin = Call("frexp", vec2(1.0f, 1.0f), AddressOf(Expr("a"))); + WrapInFunction(Decl(a), builtin); EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(TypeOf(builtin)->is_float_vector()); @@ -130,10 +128,9 @@ TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec2) { TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec3) { auto* a = Var("a", ty.vec3()); - auto* b = Const("b", ty.pointer(ty.vec3(), ast::StorageClass::kFunction), - Expr("a"), {}); - auto* builtin = Call("frexp", vec3(1.0f, 1.0f, 1.0f), Expr("b")); - WrapInFunction(Decl(a), Decl(b), builtin); + auto* builtin = + Call("frexp", vec3(1.0f, 1.0f, 1.0f), AddressOf(Expr("a"))); + WrapInFunction(Decl(a), builtin); EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(TypeOf(builtin)->is_float_vector()); @@ -142,10 +139,9 @@ TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec3) { TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec4) { auto* a = Var("a", ty.vec4()); - auto* b = Const("b", ty.pointer(ty.vec4(), ast::StorageClass::kFunction), - Expr("a"), {}); - auto* builtin = Call("frexp", vec4(1.0f, 1.0f, 1.0f, 1.0f), Expr("b")); - WrapInFunction(Decl(a), Decl(b), builtin); + auto* builtin = + Call("frexp", vec4(1.0f, 1.0f, 1.0f, 1.0f), AddressOf(Expr("a"))); + WrapInFunction(Decl(a), builtin); EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(TypeOf(builtin)->is_float_vector()); @@ -154,10 +150,8 @@ TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec4) { TEST_F(ResolverBuiltinsValidationTest, Modf_Scalar) { auto* a = Var("a", ty.f32()); - auto* b = - Const("b", ty.pointer(ast::StorageClass::kFunction), Expr("a"), {}); - auto* builtin = Call("modf", 1.0f, Expr("b")); - WrapInFunction(Decl(a), Decl(b), builtin); + auto* builtin = Call("modf", 1.0f, AddressOf(Expr("a"))); + WrapInFunction(Decl(a), builtin); EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(TypeOf(builtin)->Is()); @@ -166,10 +160,8 @@ TEST_F(ResolverBuiltinsValidationTest, Modf_Scalar) { TEST_F(ResolverBuiltinsValidationTest, Modf_Vec2) { auto* a = Var("a", ty.vec2()); - auto* b = Const("b", ty.pointer(ty.vec2(), ast::StorageClass::kFunction), - Expr("a"), {}); - auto* builtin = Call("modf", vec2(1.0f, 1.0f), Expr("b")); - WrapInFunction(Decl(a), Decl(b), builtin); + auto* builtin = Call("modf", vec2(1.0f, 1.0f), AddressOf(Expr("a"))); + WrapInFunction(Decl(a), builtin); EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(TypeOf(builtin)->is_float_vector()); @@ -178,10 +170,9 @@ TEST_F(ResolverBuiltinsValidationTest, Modf_Vec2) { TEST_F(ResolverBuiltinsValidationTest, Modf_Vec3) { auto* a = Var("a", ty.vec3()); - auto* b = Const("b", ty.pointer(ty.vec3(), ast::StorageClass::kFunction), - Expr("a"), {}); - auto* builtin = Call("modf", vec3(1.0f, 1.0f, 1.0f), Expr("b")); - WrapInFunction(Decl(a), Decl(b), builtin); + auto* builtin = + Call("modf", vec3(1.0f, 1.0f, 1.0f), AddressOf(Expr("a"))); + WrapInFunction(Decl(a), builtin); EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(TypeOf(builtin)->is_float_vector()); @@ -190,10 +181,9 @@ TEST_F(ResolverBuiltinsValidationTest, Modf_Vec3) { TEST_F(ResolverBuiltinsValidationTest, Modf_Vec4) { auto* a = Var("a", ty.vec4()); - auto* b = Const("b", ty.pointer(ty.vec4(), ast::StorageClass::kFunction), - Expr("a"), {}); - auto* builtin = Call("modf", vec4(1.0f, 1.0f, 1.0f, 1.0f), Expr("b")); - WrapInFunction(Decl(a), Decl(b), builtin); + auto* builtin = + Call("modf", vec4(1.0f, 1.0f, 1.0f, 1.0f), AddressOf(Expr("a"))); + WrapInFunction(Decl(a), builtin); EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(TypeOf(builtin)->is_float_vector()); diff --git a/src/resolver/intrinsic_test.cc b/src/resolver/intrinsic_test.cc index af7323dd36..eb704bfb55 100644 --- a/src/resolver/intrinsic_test.cc +++ b/src/resolver/intrinsic_test.cc @@ -182,7 +182,7 @@ TEST_P(ResolverIntrinsicTest_FloatMethod, TooManyParams) { EXPECT_FALSE(r()->Resolve()); EXPECT_EQ(r()->error(), "error: no matching call to " + name + - "(ptr, f32)\n\n" + "(f32, f32)\n\n" "2 candidate functions:\n " + name + "(f32) -> bool\n " + name + "(vecN) -> vecN\n"); @@ -435,9 +435,8 @@ TEST_F(ResolverIntrinsicTest, Dot_Error_VectorInt) { EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - R"(error: no matching call to dot(ptr>, ptr>) + EXPECT_EQ(r()->error(), + R"(error: no matching call to dot(vec4, vec4) 1 candidate function: dot(vecN, vecN) -> f32 @@ -793,7 +792,7 @@ TEST_F(ResolverIntrinsicDataTest, ArrayLength_Error_ArraySized) { EXPECT_FALSE(r()->Resolve()); EXPECT_EQ(r()->error(), - "error: no matching call to arrayLength(ptr>)\n\n" + "error: no matching call to arrayLength(array)\n\n" "1 candidate function:\n" " arrayLength(array) -> u32\n"); } @@ -823,7 +822,7 @@ TEST_F(ResolverIntrinsicDataTest, Normalize_Error_NoParams) { TEST_F(ResolverIntrinsicDataTest, FrexpScalar) { Global("exp", ty.i32(), ast::StorageClass::kWorkgroup); - auto* call = Call("frexp", 1.0f, "exp"); + auto* call = Call("frexp", 1.0f, AddressOf("exp")); WrapInFunction(call); EXPECT_TRUE(r()->Resolve()) << r()->error(); @@ -834,7 +833,7 @@ TEST_F(ResolverIntrinsicDataTest, FrexpScalar) { TEST_F(ResolverIntrinsicDataTest, FrexpVector) { Global("exp", ty.vec3(), ast::StorageClass::kWorkgroup); - auto* call = Call("frexp", vec3(1.0f, 2.0f, 3.0f), "exp"); + auto* call = Call("frexp", vec3(1.0f, 2.0f, 3.0f), AddressOf("exp")); WrapInFunction(call); EXPECT_TRUE(r()->Resolve()) << r()->error(); @@ -846,7 +845,7 @@ TEST_F(ResolverIntrinsicDataTest, FrexpVector) { TEST_F(ResolverIntrinsicDataTest, Frexp_Error_FirstParamInt) { Global("exp", ty.i32(), ast::StorageClass::kWorkgroup); - auto* call = Call("frexp", 1, "exp"); + auto* call = Call("frexp", 1, AddressOf("exp")); WrapInFunction(call); EXPECT_FALSE(r()->Resolve()); @@ -861,7 +860,7 @@ TEST_F(ResolverIntrinsicDataTest, Frexp_Error_FirstParamInt) { TEST_F(ResolverIntrinsicDataTest, Frexp_Error_SecondParamFloatPtr) { Global("exp", ty.f32(), ast::StorageClass::kWorkgroup); - auto* call = Call("frexp", 1.0f, "exp"); + auto* call = Call("frexp", 1.0f, AddressOf("exp")); WrapInFunction(call); EXPECT_FALSE(r()->Resolve()); @@ -890,23 +889,24 @@ TEST_F(ResolverIntrinsicDataTest, Frexp_Error_SecondParamNotAPointer) { TEST_F(ResolverIntrinsicDataTest, Frexp_Error_VectorSizesDontMatch) { Global("exp", ty.vec4(), ast::StorageClass::kWorkgroup); - auto* call = Call("frexp", vec2(1.0f, 2.0f), "exp"); + auto* call = Call("frexp", vec2(1.0f, 2.0f), AddressOf("exp")); WrapInFunction(call); EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "error: no matching call to frexp(vec2, ptr>)\n\n" - "2 candidate functions:\n" - " frexp(f32, ptr) -> f32 where: T is i32 or u32\n" - " frexp(vecN, ptr>) -> vecN " - "where: T is i32 or u32\n"); + EXPECT_EQ( + r()->error(), + R"(error: no matching call to frexp(vec2, ptr>) + +2 candidate functions: + frexp(f32, ptr) -> f32 where: T is i32 or u32 + frexp(vecN, ptr>) -> vecN where: T is i32 or u32 +)"); } TEST_F(ResolverIntrinsicDataTest, ModfScalar) { Global("whole", ty.f32(), ast::StorageClass::kWorkgroup); - auto* call = Call("modf", 1.0f, "whole"); + auto* call = Call("modf", 1.0f, AddressOf("whole")); WrapInFunction(call); EXPECT_TRUE(r()->Resolve()) << r()->error(); @@ -917,7 +917,7 @@ TEST_F(ResolverIntrinsicDataTest, ModfScalar) { TEST_F(ResolverIntrinsicDataTest, ModfVector) { Global("whole", ty.vec3(), ast::StorageClass::kWorkgroup); - auto* call = Call("modf", vec3(1.0f, 2.0f, 3.0f), "whole"); + auto* call = Call("modf", vec3(1.0f, 2.0f, 3.0f), AddressOf("whole")); WrapInFunction(call); EXPECT_TRUE(r()->Resolve()) << r()->error(); @@ -929,7 +929,7 @@ TEST_F(ResolverIntrinsicDataTest, ModfVector) { TEST_F(ResolverIntrinsicDataTest, Modf_Error_FirstParamInt) { Global("whole", ty.f32(), ast::StorageClass::kWorkgroup); - auto* call = Call("modf", 1, "whole"); + auto* call = Call("modf", 1, AddressOf("whole")); WrapInFunction(call); EXPECT_FALSE(r()->Resolve()); @@ -943,7 +943,7 @@ TEST_F(ResolverIntrinsicDataTest, Modf_Error_FirstParamInt) { TEST_F(ResolverIntrinsicDataTest, Modf_Error_SecondParamIntPtr) { Global("whole", ty.i32(), ast::StorageClass::kWorkgroup); - auto* call = Call("modf", 1.0f, "whole"); + auto* call = Call("modf", 1.0f, AddressOf("whole")); WrapInFunction(call); EXPECT_FALSE(r()->Resolve()); @@ -970,17 +970,19 @@ TEST_F(ResolverIntrinsicDataTest, Modf_Error_SecondParamNotAPointer) { TEST_F(ResolverIntrinsicDataTest, Modf_Error_VectorSizesDontMatch) { Global("whole", ty.vec4(), ast::StorageClass::kWorkgroup); - auto* call = Call("modf", vec2(1.0f, 2.0f), "whole"); + auto* call = Call("modf", vec2(1.0f, 2.0f), AddressOf("whole")); WrapInFunction(call); EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "error: no matching call to modf(vec2, ptr>)\n\n" - "2 candidate functions:\n" - " modf(vecN, ptr>) -> vecN\n" - " modf(f32, ptr) -> f32\n"); + EXPECT_EQ( + r()->error(), + R"(error: no matching call to modf(vec2, ptr>) + +2 candidate functions: + modf(vecN, ptr>) -> vecN + modf(f32, ptr) -> f32 +)"); } using ResolverIntrinsicTest_SingleParam_FloatOrInt = @@ -1652,11 +1654,10 @@ TEST_F(ResolverIntrinsicTest, Determinant_NotSquare) { EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "error: no matching call to determinant(ptr>)\n\n" - "1 candidate function:\n" - " determinant(matNxN) -> f32\n"); + EXPECT_EQ(r()->error(), + "error: no matching call to determinant(mat2x3)\n\n" + "1 candidate function:\n" + " determinant(matNxN) -> f32\n"); } TEST_F(ResolverIntrinsicTest, Determinant_NotMatrix) { @@ -1668,7 +1669,7 @@ TEST_F(ResolverIntrinsicTest, Determinant_NotMatrix) { EXPECT_FALSE(r()->Resolve()); EXPECT_EQ(r()->error(), - "error: no matching call to determinant(ptr)\n\n" + "error: no matching call to determinant(f32)\n\n" "1 candidate function:\n" " determinant(matNxN) -> f32\n"); } diff --git a/src/resolver/ptr_ref_test.cc b/src/resolver/ptr_ref_test.cc new file mode 100644 index 0000000000..e66a0ceae2 --- /dev/null +++ b/src/resolver/ptr_ref_test.cc @@ -0,0 +1,62 @@ +// 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/resolver/resolver.h" +#include "src/resolver/resolver_test_helper.h" +#include "src/sem/reference_type.h" + +#include "gmock/gmock.h" + +namespace tint { +namespace resolver { +namespace { + +struct ResolverPtrRefTest : public resolver::TestHelper, + public testing::Test {}; + +TEST_F(ResolverPtrRefTest, AddressOf) { + // var v : i32; + // &v + + auto* v = Var("v", ty.i32(), ast::StorageClass::kNone); + auto* expr = AddressOf(v); + + WrapInFunction(v, expr); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_TRUE(TypeOf(expr)->Is()); + EXPECT_TRUE(TypeOf(expr)->As()->StoreType()->Is()); + EXPECT_EQ(TypeOf(expr)->As()->StorageClass(), + ast::StorageClass::kFunction); +} + +TEST_F(ResolverPtrRefTest, AddressOfThenDeref) { + // var v : i32; + // *(&v) + + auto* v = Var("v", ty.i32(), ast::StorageClass::kNone); + auto* expr = Deref(AddressOf(v)); + + WrapInFunction(v, expr); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_TRUE(TypeOf(expr)->Is()); + EXPECT_TRUE(TypeOf(expr)->As()->StoreType()->Is()); +} + +} // namespace +} // namespace resolver +} // namespace tint diff --git a/src/resolver/ptr_ref_validation_test.cc b/src/resolver/ptr_ref_validation_test.cc new file mode 100644 index 0000000000..0b2d07d72d --- /dev/null +++ b/src/resolver/ptr_ref_validation_test.cc @@ -0,0 +1,82 @@ +// 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/resolver/resolver.h" +#include "src/resolver/resolver_test_helper.h" +#include "src/sem/reference_type.h" + +#include "gmock/gmock.h" + +namespace tint { +namespace resolver { +namespace { + +struct ResolverPtrRefValidationTest : public resolver::TestHelper, + public testing::Test {}; + +TEST_F(ResolverPtrRefValidationTest, AddressOfLiteral) { + // &1 + + auto* expr = AddressOf(Expr(Source{{12, 34}}, 1)); + + WrapInFunction(expr); + + EXPECT_FALSE(r()->Resolve()); + + EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of expression"); +} + +TEST_F(ResolverPtrRefValidationTest, AddressOfLet) { + // let l : i32 = 1; + // &l + auto* l = Const("l", ty.i32(), Expr(1)); + auto* expr = AddressOf(Expr(Source{{12, 34}}, "l")); + + WrapInFunction(l, expr); + + EXPECT_FALSE(r()->Resolve()); + + EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of expression"); +} + +TEST_F(ResolverPtrRefValidationTest, DerefOfLiteral) { + // *1 + + auto* expr = Deref(Expr(Source{{12, 34}}, 1)); + + WrapInFunction(expr); + + EXPECT_FALSE(r()->Resolve()); + + EXPECT_EQ(r()->error(), + "12:34 error: cannot dereference expression of type 'i32'"); +} + +TEST_F(ResolverPtrRefValidationTest, DerefOfVar) { + // var v : i32 = 1; + // *1 + auto* v = Var("v", ty.i32()); + auto* expr = Deref(Expr(Source{{12, 34}}, "v")); + + WrapInFunction(v, expr); + + EXPECT_FALSE(r()->Resolve()); + + EXPECT_EQ(r()->error(), + "12:34 error: cannot dereference expression of type 'i32'"); +} + +} // namespace +} // namespace resolver +} // namespace tint diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc index 67b07340cf..a5e33799b2 100644 --- a/src/resolver/resolver.cc +++ b/src/resolver/resolver.cc @@ -53,6 +53,7 @@ #include "src/sem/member_accessor_expression.h" #include "src/sem/multisampled_texture_type.h" #include "src/sem/pointer_type.h" +#include "src/sem/reference_type.h" #include "src/sem/sampled_texture_type.h" #include "src/sem/sampler_type.h" #include "src/sem/statement.h" @@ -226,22 +227,6 @@ bool Resolver::IsHostShareable(const sem::Type* type) { return false; } -bool Resolver::IsValidAssignment(const sem::Type* lhs, const sem::Type* rhs) { - // TODO(crbug.com/tint/659): This is a rough approximation, and is missing - // checks for writability of pointer storage class, access control, etc. - // This will need to be fixed after WGSL agrees the behavior of pointers / - // references. - // Check: - if (lhs->UnwrapAccess() != rhs->UnwrapAccess()) { - // Try RHS dereference - if (lhs->UnwrapAccess() != rhs->UnwrapAll()) { - return false; - } - } - - return true; -} - bool Resolver::ResolveInternal() { Mark(&builder_->AST()); @@ -438,7 +423,7 @@ sem::Type* Resolver::Type(const ast::Type* ty) { } Resolver::VariableInfo* Resolver::Variable(ast::Variable* var, - bool is_parameter) { + VariableKind kind) { if (variable_to_info_.count(var)) { TINT_ICE(diagnostics_) << "Variable " << builder_->Symbols().NameFor(var->symbol()) @@ -446,17 +431,21 @@ Resolver::VariableInfo* Resolver::Variable(ast::Variable* var, return nullptr; } - // If the variable has a declared type, resolve it. std::string type_name; - const sem::Type* type = nullptr; + const sem::Type* storage_type = nullptr; + + // If the variable has a declared type, resolve it. if (auto* ty = var->type()) { type_name = ty->FriendlyName(builder_->Symbols()); - type = Type(ty); - if (!type) { + storage_type = Type(ty); + if (!storage_type) { return nullptr; } } + std::string rhs_type_name; + const sem::Type* rhs_type = nullptr; + // Does the variable have a constructor? if (auto* ctor = var->constructor()) { Mark(var->constructor()); @@ -465,32 +454,57 @@ Resolver::VariableInfo* Resolver::Variable(ast::Variable* var, } // Fetch the constructor's type - auto* rhs_type = TypeOf(ctor); + rhs_type_name = TypeNameOf(ctor); + rhs_type = TypeOf(ctor); if (!rhs_type) { return nullptr; } // If the variable has no declared type, infer it from the RHS - if (type == nullptr) { - type_name = TypeNameOf(ctor); - type = rhs_type->UnwrapPtr(); + if (!storage_type) { + type_name = rhs_type_name; + storage_type = rhs_type->UnwrapRef(); // Implicit load of RHS } - - if (!IsValidAssignment(type, rhs_type)) { - diagnostics_.add_error( - "variable of type '" + type_name + - "' cannot be initialized with a value of type '" + - TypeNameOf(ctor) + "'", - var->source()); - return nullptr; - } - } else if (var->is_const() && !is_parameter && + } else if (var->is_const() && kind != VariableKind::kParameter && !ast::HasDecoration(var->decorations())) { diagnostics_.add_error("let declarations must have initializers", var->source()); return nullptr; } + if (!storage_type) { + TINT_ICE(diagnostics_) + << "failed to determine storage type for variable '" + + builder_->Symbols().NameFor(var->symbol()) + "'\n" + << "Source: " << var->source(); + return nullptr; + } + + auto storage_class = var->declared_storage_class(); + if (storage_class == ast::StorageClass::kNone) { + if (storage_type->UnwrapRef()->is_handle()) { + // https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables + // If the store type is a texture type or a sampler type, then the + // variable declaration must not have a storage class decoration. The + // storage class will always be handle. + storage_class = ast::StorageClass::kUniformConstant; + } else if (kind == VariableKind::kLocal && !var->is_const()) { + storage_class = ast::StorageClass::kFunction; + } + } + + auto* type = storage_type; + if (!var->is_const()) { + // Variable declaration. Unlike `let`, `var` has storage. + // Variables are always of a reference type to the declared storage type. + type = builder_->create(storage_type, storage_class); + } + + if (rhs_type && !ValidateVariableConstructor(var, storage_type, type_name, + rhs_type, rhs_type_name)) { + return nullptr; + } + // TODO(crbug.com/tint/802): Temporary while ast::AccessControl exits. auto find_first_access_control = [this](ast::Type* ty) -> ast::AccessControl* { @@ -519,12 +533,39 @@ Resolver::VariableInfo* Resolver::Variable(ast::Variable* var, } auto* info = variable_infos_.Create(var, const_cast(type), - type_name, access_control); + type_name, storage_class, access_control); variable_to_info_.emplace(var, info); return info; } +bool Resolver::ValidateVariableConstructor(const ast::Variable* var, + const sem::Type* storage_type, + const std::string& type_name, + const sem::Type* rhs_type, + const std::string& rhs_type_name) { + auto* value_type = rhs_type->UnwrapRef(); // Implicit load of RHS + + // RHS needs to be of a storable type + if (!var->is_const() && !IsStorable(value_type)) { + diagnostics_.add_error( + "'" + rhs_type_name + "' is not storable for assignment", + var->constructor()->source()); + return false; + } + + // Value type has to match storage type + if (storage_type->UnwrapAccess() != value_type->UnwrapAccess()) { + std::string decl = var->is_const() ? "let" : "var"; + diagnostics_.add_error("cannot initialize " + decl + " of type '" + + type_name + "' with value of type '" + + rhs_type_name + "'", + var->source()); + return false; + } + return true; +} + bool Resolver::GlobalVariable(ast::Variable* var) { if (variable_stack_.has(var->symbol())) { diagnostics_.add_error("v-0011", @@ -534,7 +575,7 @@ bool Resolver::GlobalVariable(ast::Variable* var) { return false; } - auto* info = Variable(var, /* is_parameter */ false); + auto* info = Variable(var, VariableKind::kGlobal); if (!info) { return false; } @@ -571,8 +612,9 @@ bool Resolver::GlobalVariable(ast::Variable* var) { return false; } - if (!ApplyStorageClassUsageToType(info->storage_class, info->type, - var->source())) { + if (!ApplyStorageClassUsageToType( + info->storage_class, const_cast(info->type->UnwrapRef()), + var->source())) { diagnostics_.add_note("while instantiating variable " + builder_->Symbols().NameFor(var->symbol()), var->source()); @@ -636,7 +678,8 @@ bool Resolver::ValidateGlobalVariable(const VariableInfo* info) { // attributes. if (!binding_point) { diagnostics_.add_error( - "resource variables require [[group]] and [[binding]] decorations", + "resource variables require [[group]] and [[binding]] " + "decorations", info->declaration->source()); return false; } @@ -666,7 +709,7 @@ bool Resolver::ValidateGlobalVariable(const VariableInfo* info) { // attribute, satisfying the storage class constraints. auto* str = info->access_control != ast::AccessControl::kInvalid - ? info->type->As() + ? info->type->UnwrapRef()->As() : nullptr; if (!str) { @@ -695,7 +738,7 @@ bool Resolver::ValidateGlobalVariable(const VariableInfo* info) { // A variable in the uniform storage class is a uniform buffer variable. // Its store type must be a host-shareable structure type with block // attribute, satisfying the storage class constraints. - auto* str = info->type->As(); + auto* str = info->type->UnwrapRef()->As(); if (!str) { diagnostics_.add_error( "variables declared in the storage class must be of a " @@ -726,8 +769,8 @@ bool Resolver::ValidateGlobalVariable(const VariableInfo* info) { bool Resolver::ValidateVariable(const VariableInfo* info) { auto* var = info->declaration; - auto* type = info->type; - if (auto* r = type->As()) { + auto* storage_type = info->type->UnwrapRef(); + if (auto* r = storage_type->As()) { if (r->IsRuntimeSized()) { diagnostics_.add_error( "v-0015", @@ -737,15 +780,14 @@ bool Resolver::ValidateVariable(const VariableInfo* info) { } } - if (auto* r = type->As()) { + if (auto* r = storage_type->As()) { if (r->dim() != ast::TextureDimension::k2d) { diagnostics_.add_error("Only 2d multisampled textures are supported", var->source()); return false; } - auto* data_type = r->type()->UnwrapAll(); - if (!data_type->is_numeric_scalar()) { + if (!r->type()->UnwrapRef()->is_numeric_scalar()) { diagnostics_.add_error( "texture_multisampled_2d: type must be f32, i32 or u32", var->source()); @@ -753,7 +795,7 @@ bool Resolver::ValidateVariable(const VariableInfo* info) { } } - if (auto* storage_tex = type->As()) { + if (auto* storage_tex = info->type->UnwrapRef()->As()) { if (storage_tex->access_control() == ast::AccessControl::kInvalid) { diagnostics_.add_error("Storage Textures must have access control.", var->source()); @@ -786,12 +828,12 @@ bool Resolver::ValidateVariable(const VariableInfo* info) { } } - if (type->UnwrapAll()->is_handle() && + if (storage_type->is_handle() && var->declared_storage_class() != ast::StorageClass::kNone) { // https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables - // If the store type is a texture type or a sampler type, then the variable - // declaration must not have a storage class decoration. The storage class - // will always be handle. + // If the store type is a texture type or a sampler type, then the + // variable declaration must not have a storage class decoration. The + // storage class will always be handle. diagnostics_.add_error("variables of type '" + info->type_name + "' must not have a storage class", var->source()); @@ -893,10 +935,10 @@ bool Resolver::ValidateFunction(const ast::Function* func, bool Resolver::ValidateEntryPoint(const ast::Function* func, const FunctionInfo* info) { // Use a lambda to validate the entry point decorations for a type. - // Persistent state is used to track which builtins and locations have already - // been seen, in order to catch conflicts. - // TODO(jrprice): This state could be stored in FunctionInfo instead, and then - // passed to sem::Function since it would be useful there too. + // Persistent state is used to track which builtins and locations have + // already been seen, in order to catch conflicts. + // TODO(jrprice): This state could be stored in FunctionInfo instead, and + // then passed to sem::Function since it would be useful there too. std::unordered_set builtins; std::unordered_set locations; enum class ParamOrRetType { @@ -1147,7 +1189,7 @@ bool Resolver::Function(ast::Function* func) { variable_stack_.push_scope(); for (auto* param : func->params()) { Mark(param); - auto* param_info = Variable(param, /* is_parameter */ true); + auto* param_info = Variable(param, VariableKind::kParameter); if (!param_info) { return false; } @@ -1377,7 +1419,7 @@ bool Resolver::IfStatement(ast::IfStatement* stmt) { return false; } - auto* cond_type = TypeOf(stmt->condition())->UnwrapAll(); + auto* cond_type = TypeOf(stmt->condition())->UnwrapRef(); if (cond_type != builder_->ty.bool_()) { diagnostics_.add_error("if statement condition must be bool, got " + cond_type->FriendlyName(builder_->Symbols()), @@ -1409,7 +1451,7 @@ bool Resolver::IfStatement(ast::IfStatement* stmt) { return false; } - auto* else_cond_type = TypeOf(cond)->UnwrapAll(); + auto* else_cond_type = TypeOf(cond)->UnwrapRef(); if (else_cond_type != builder_->ty.bool_()) { diagnostics_.add_error( "else statement condition must be bool, got " + @@ -1525,7 +1567,7 @@ bool Resolver::ArrayAccessor(ast::ArrayAccessorExpression* expr) { } auto* res = TypeOf(expr->array()); - auto* parent_type = res->UnwrapAll(); + auto* parent_type = res->UnwrapRef(); const sem::Type* ret = nullptr; if (auto* arr = parent_type->As()) { ret = arr->ElemType(); @@ -1540,15 +1582,9 @@ bool Resolver::ArrayAccessor(ast::ArrayAccessorExpression* expr) { return false; } - // If we're extracting from a pointer, we return a pointer. - if (auto* ptr = res->As()) { - ret = builder_->create(ret, ptr->StorageClass()); - } else if (auto* arr = parent_type->As()) { - if (!arr->ElemType()->is_scalar()) { - // If we extract a non-scalar from an array then we also get a pointer. We - // will generate a Function storage class variable to store this into. - ret = builder_->create(ret, ast::StorageClass::kFunction); - } + // If we're extracting from a reference, we return a reference. + if (auto* ref = res->As()) { + ret = builder_->create(ret, ref->StorageClass()); } SetType(expr, ret); @@ -1569,9 +1605,9 @@ bool Resolver::Call(ast::CallExpression* call) { return false; } - // The expression has to be an identifier as you can't store function pointers - // but, if it isn't we'll just use the normal result determination to be on - // the safe side. + // The expression has to be an identifier as you can't store function + // pointers but, if it isn't we'll just use the normal result determination + // to be on the safe side. Mark(call->func()); auto* ident = call->func()->As(); if (!ident) { @@ -1605,7 +1641,8 @@ bool Resolver::Call(ast::CallExpression* call) { auto* callee_func = callee_func_it->second; // Note: Requires called functions to be resolved first. - // This is currently guaranteed as functions must be declared before use. + // This is currently guaranteed as functions must be declared before + // use. current_function_->transitive_calls.add(callee_func); for (auto* transitive_call : callee_func->transitive_calls) { current_function_->transitive_calls.add(transitive_call); @@ -1692,10 +1729,10 @@ bool Resolver::ValidateVectorConstructor( const ast::TypeConstructorExpression* ctor, const sem::Vector* vec_type) { auto& values = ctor->values(); - auto* elem_type = vec_type->type()->UnwrapAll(); + auto* elem_type = vec_type->type(); size_t value_cardinality_sum = 0; for (auto* value : values) { - auto* value_type = TypeOf(value)->UnwrapAll(); + auto* value_type = TypeOf(value)->UnwrapRef(); if (value_type->is_scalar()) { if (elem_type != value_type) { diagnostics_.add_error( @@ -1709,7 +1746,7 @@ bool Resolver::ValidateVectorConstructor( value_cardinality_sum++; } else if (auto* value_vec = value_type->As()) { - auto* value_elem_type = value_vec->type()->UnwrapAll(); + auto* value_elem_type = value_vec->type(); // A mismatch of vector type parameter T is only an error if multiple // arguments are present. A single argument constructor constitutes a // type conversion expression. @@ -1766,7 +1803,7 @@ bool Resolver::ValidateMatrixConstructor( return true; } - auto* elem_type = matrix_type->type()->UnwrapAll(); + auto* elem_type = matrix_type->type(); if (matrix_type->columns() != values.size()) { const Source& values_start = values[0]->source(); const Source& values_end = values[values.size() - 1]->source(); @@ -1780,11 +1817,11 @@ bool Resolver::ValidateMatrixConstructor( } for (auto* value : values) { - auto* value_type = TypeOf(value)->UnwrapAll(); + auto* value_type = TypeOf(value)->UnwrapRef(); auto* value_vec = value_type->As(); if (!value_vec || value_vec->size() != matrix_type->rows() || - elem_type != value_vec->type()->UnwrapAll()) { + elem_type != value_vec->type()) { diagnostics_.add_error("expected argument type '" + VectorPretty(matrix_type->rows(), elem_type) + "' in '" + TypeNameOf(ctor) + @@ -1802,26 +1839,15 @@ bool Resolver::Identifier(ast::IdentifierExpression* expr) { auto symbol = expr->symbol(); VariableInfo* var; if (variable_stack_.get(symbol, &var)) { - // A constant is the type, but a variable is always a pointer so synthesize - // the pointer around the variable type. - if (var->declaration->is_const()) { - SetType(expr, var->type, var->type_name); - } else if (var->type->Is()) { - SetType(expr, var->type, var->type_name); - } else { - SetType(expr, - builder_->create(const_cast(var->type), - var->storage_class), - var->type_name); - } + SetType(expr, var->type, var->type_name); var->users.push_back(expr); set_referenced_from_function_if_needed(var, true); if (current_block_) { - // If identifier is part of a loop continuing block, make sure it doesn't - // refer to a variable that is bypassed by a continue statement in the - // loop's body block. + // If identifier is part of a loop continuing block, make sure it + // doesn't refer to a variable that is bypassed by a continue statement + // in the loop's body block. if (auto* continuing_block = current_block_->FindFirstParent( sem::BlockStatement::Type::kLoopContinuing)) { auto* loop_block = @@ -1878,13 +1904,13 @@ bool Resolver::MemberAccessor(ast::MemberAccessorExpression* expr) { return false; } - auto* res = TypeOf(expr->structure()); - auto* data_type = res->UnwrapAll(); + auto* structure = TypeOf(expr->structure()); + auto* storage_type = structure->UnwrapRef(); sem::Type* ret = nullptr; std::vector swizzle; - if (auto* str = data_type->As()) { + if (auto* str = storage_type->As()) { Mark(expr->member()); auto symbol = expr->member()->symbol(); @@ -1904,14 +1930,14 @@ bool Resolver::MemberAccessor(ast::MemberAccessorExpression* expr) { return false; } - // If we're extracting from a pointer, we return a pointer. - if (auto* ptr = res->As()) { - ret = builder_->create(ret, ptr->StorageClass()); + // If we're extracting from a reference, we return a reference. + if (auto* ref = structure->As()) { + ret = builder_->create(ret, ref->StorageClass()); } builder_->Sem().Add(expr, builder_->create( expr, ret, current_statement_, member)); - } else if (auto* vec = data_type->As()) { + } else if (auto* vec = storage_type->As()) { Mark(expr->member()); std::string s = builder_->Symbols().NameFor(expr->member()->symbol()); auto size = s.size(); @@ -1967,9 +1993,9 @@ bool Resolver::MemberAccessor(ast::MemberAccessorExpression* expr) { if (size == 1) { // A single element swizzle is just the type of the vector. ret = vec->type(); - // If we're extracting from a pointer, we return a pointer. - if (auto* ptr = res->As()) { - ret = builder_->create(ret, ptr->StorageClass()); + // If we're extracting from a reference, we return a reference. + if (auto* ref = structure->As()) { + ret = builder_->create(ret, ref->StorageClass()); } } else { // The vector will have a number of components equal to the length of @@ -1983,7 +2009,7 @@ bool Resolver::MemberAccessor(ast::MemberAccessorExpression* expr) { } else { diagnostics_.add_error( "invalid use of member accessor on a non-vector/non-struct " + - data_type->type_name(), + TypeNameOf(expr->structure()), expr->source()); return false; } @@ -2001,8 +2027,8 @@ bool Resolver::ValidateBinary(ast::BinaryExpression* expr) { using Matrix = sem::Matrix; using Vector = sem::Vector; - auto* lhs_type = const_cast(TypeOf(expr->lhs())->UnwrapAll()); - auto* rhs_type = const_cast(TypeOf(expr->rhs())->UnwrapAll()); + auto* lhs_type = const_cast(TypeOf(expr->lhs())->UnwrapRef()); + auto* rhs_type = const_cast(TypeOf(expr->rhs())->UnwrapRef()); auto* lhs_vec = lhs_type->As(); auto* lhs_vec_elem_type = lhs_vec ? lhs_vec->type() : nullptr; @@ -2169,7 +2195,7 @@ bool Resolver::Binary(ast::BinaryExpression* expr) { if (expr->IsAnd() || expr->IsOr() || expr->IsXor() || expr->IsShiftLeft() || expr->IsShiftRight() || expr->IsAdd() || expr->IsSubtract() || expr->IsDivide() || expr->IsModulo()) { - SetType(expr, TypeOf(expr->lhs())->UnwrapPtr()); + SetType(expr, TypeOf(expr->lhs())->UnwrapRef()); return true; } // Result type is a scalar or vector of boolean type @@ -2177,7 +2203,7 @@ bool Resolver::Binary(ast::BinaryExpression* expr) { expr->IsNotEqual() || expr->IsLessThan() || expr->IsGreaterThan() || expr->IsLessThanEqual() || expr->IsGreaterThanEqual()) { auto* bool_type = builder_->create(); - auto* param_type = TypeOf(expr->lhs())->UnwrapAll(); + auto* param_type = TypeOf(expr->lhs())->UnwrapRef(); sem::Type* result_type = bool_type; if (auto* vec = param_type->As()) { result_type = builder_->create(bool_type, vec->size()); @@ -2186,8 +2212,8 @@ bool Resolver::Binary(ast::BinaryExpression* expr) { return true; } if (expr->IsMultiply()) { - auto* lhs_type = TypeOf(expr->lhs())->UnwrapAll(); - auto* rhs_type = TypeOf(expr->rhs())->UnwrapAll(); + auto* lhs_type = TypeOf(expr->lhs())->UnwrapRef(); + auto* rhs_type = TypeOf(expr->rhs())->UnwrapRef(); // Note, the ordering here matters. The later checks depend on the prior // checks having been done. @@ -2234,16 +2260,55 @@ bool Resolver::Binary(ast::BinaryExpression* expr) { return false; } -bool Resolver::UnaryOp(ast::UnaryOpExpression* expr) { - Mark(expr->expr()); +bool Resolver::UnaryOp(ast::UnaryOpExpression* unary) { + Mark(unary->expr()); - // Result type matches the parameter type. - if (!Expression(expr->expr())) { + // Resolve the inner expression + if (!Expression(unary->expr())) { return false; } - auto* result_type = TypeOf(expr->expr())->UnwrapPtr(); - SetType(expr, result_type); + auto* expr_type = TypeOf(unary->expr()); + if (!expr_type) { + return false; + } + + std::string type_name; + const sem::Type* type = nullptr; + + switch (unary->op()) { + case ast::UnaryOp::kNegation: + case ast::UnaryOp::kNot: + // Result type matches the deref'd inner type. + type_name = TypeNameOf(unary->expr()); + type = expr_type->UnwrapRef(); + break; + + case ast::UnaryOp::kAddressOf: + if (auto* ref = expr_type->As()) { + type = builder_->create(ref->StoreType(), + ref->StorageClass()); + } else { + diagnostics_.add_error("cannot take the address of expression", + unary->expr()->source()); + return false; + } + break; + + case ast::UnaryOp::kIndirection: + if (auto* ptr = expr_type->As()) { + type = builder_->create(ptr->StoreType(), + ptr->StorageClass()); + } else { + diagnostics_.add_error("cannot dereference expression of type '" + + TypeNameOf(unary->expr()) + "'", + unary->expr()->source()); + return false; + } + break; + } + + SetType(unary, type); return true; } @@ -2257,11 +2322,11 @@ bool Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) { diagnostics_.add_error(error_code, "redeclared identifier '" + builder_->Symbols().NameFor(var->symbol()) + "'", - stmt->source()); + var->source()); return false; } - auto* info = Variable(var, /* is_parameter */ false); + auto* info = Variable(var, VariableKind::kLocal); if (!info) { return false; } @@ -2357,8 +2422,8 @@ void Resolver::SetType(ast::Expression* expr, void Resolver::CreateSemanticNodes() const { auto& sem = builder_->Sem(); - // Collate all the 'ancestor_entry_points' - this is a map of function symbol - // to all the entry points that transitively call the function. + // Collate all the 'ancestor_entry_points' - this is a map of function + // symbol to all the entry points that transitively call the function. std::unordered_map> ancestor_entry_points; for (auto* func : builder_->AST().Functions()) { auto it = function_to_info_.find(func); @@ -2641,7 +2706,7 @@ bool Resolver::ValidateArrayStrideDecoration(const ast::StrideDecoration* deco, bool Resolver::ValidateStructure(const sem::Struct* str) { for (auto* member : str->Members()) { - if (auto* r = member->Type()->UnwrapAll()->As()) { + if (auto* r = member->Type()->As()) { if (r->IsRuntimeSized()) { if (member != str->Members().back()) { diagnostics_.add_error( @@ -2738,8 +2803,8 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) { for (auto* deco : member->decorations()) { Mark(deco); if (auto* o = deco->As()) { - // Offset decorations are not part of the WGSL spec, but are emitted by - // the SPIR-V reader. + // Offset decorations are not part of the WGSL spec, but are emitted + // by the SPIR-V reader. if (o->offset() < struct_size) { diagnostics_.add_error("offsets must be in ascending order", o->source()); @@ -2805,10 +2870,10 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) { bool Resolver::ValidateReturn(const ast::ReturnStatement* ret) { auto* func_type = current_function_->return_type; - auto* ret_type = ret->has_value() ? TypeOf(ret->value())->UnwrapAll() + auto* ret_type = ret->has_value() ? TypeOf(ret->value())->UnwrapRef() : builder_->ty.void_(); - if (func_type->UnwrapAll() != ret_type) { + if (func_type->UnwrapRef() != ret_type) { diagnostics_.add_error("v-000y", "return statement type must match its function " "return type, returned '" + @@ -2828,8 +2893,8 @@ bool Resolver::Return(ast::ReturnStatement* ret) { if (auto* value = ret->value()) { Mark(value); - // Validate after processing the return value expression so that its type is - // available for validation + // Validate after processing the return value expression so that its type + // is available for validation return Expression(value) && ValidateReturn(ret); } @@ -2837,7 +2902,7 @@ bool Resolver::Return(ast::ReturnStatement* ret) { } bool Resolver::ValidateSwitch(const ast::SwitchStatement* s) { - auto* cond_type = TypeOf(s->condition())->UnwrapAll(); + auto* cond_type = TypeOf(s->condition())->UnwrapRef(); if (!cond_type->is_integer_scalar()) { diagnostics_.add_error("v-0025", "switch statement selector expression must be of a " @@ -2928,67 +2993,6 @@ bool Resolver::Switch(ast::SwitchStatement* s) { return true; } -bool Resolver::ValidateAssignment(const ast::AssignmentStatement* a) { - auto* lhs = a->lhs(); - auto* rhs = a->rhs(); - - // TODO(crbug.com/tint/659): This logic needs updating once pointers are - // pinned down in the WGSL spec. - auto* lhs_type = TypeOf(lhs)->UnwrapAll(); - auto* rhs_type = TypeOf(rhs); - if (!IsValidAssignment(lhs_type, rhs_type)) { - diagnostics_.add_error("invalid assignment: cannot assign value of type '" + - rhs_type->FriendlyName(builder_->Symbols()) + - "' to a variable of type '" + - lhs_type->FriendlyName(builder_->Symbols()) + - "'", - a->source()); - return false; - } - - // Pointers are not storable in WGSL, but the right-hand side must be - // storable. The raw right-hand side might be a pointer value which must be - // loaded (dereferenced) to provide the value to be stored. - auto* rhs_result_type = TypeOf(rhs)->UnwrapAll(); - if (!IsStorable(rhs_result_type)) { - diagnostics_.add_error( - "v-000x", - "invalid assignment: right-hand-side is not storable: " + - TypeOf(rhs)->FriendlyName(builder_->Symbols()), - a->source()); - return false; - } - - // lhs must be a pointer or a constant - auto* lhs_result_type = TypeOf(lhs)->UnwrapAccess(); - if (!lhs_result_type->Is()) { - // In case lhs is a constant identifier, output a nicer message as it's - // likely to be a common programmer error. - if (auto* ident = lhs->As()) { - VariableInfo* var; - if (variable_stack_.get(ident->symbol(), &var) && - var->declaration->is_const()) { - diagnostics_.add_error( - "v-0021", - "cannot re-assign a constant: '" + - builder_->Symbols().NameFor(ident->symbol()) + "'", - a->source()); - return false; - } - } - - // Issue a generic error. - diagnostics_.add_error( - "v-000x", - "invalid assignment: left-hand-side does not reference storage: " + - TypeOf(lhs)->FriendlyName(builder_->Symbols()), - a->source()); - return false; - } - - return true; -} - bool Resolver::Assignment(ast::AssignmentStatement* a) { Mark(a->lhs()); Mark(a->rhs()); @@ -2999,10 +3003,52 @@ bool Resolver::Assignment(ast::AssignmentStatement* a) { return ValidateAssignment(a); } +bool Resolver::ValidateAssignment(const ast::AssignmentStatement* a) { + // https://gpuweb.github.io/gpuweb/wgsl/#assignment-statement + auto const* lhs_type = TypeOf(a->lhs()); + auto const* rhs_type = TypeOf(a->rhs()); + + auto* lhs_ref = lhs_type->As(); + if (!lhs_ref) { + // LHS is not a reference, so it has no storage. + diagnostics_.add_error( + "cannot assign to value of type '" + TypeNameOf(a->lhs()) + "'", + a->lhs()->source()); + + return false; + } + + auto* storage_type_with_access = lhs_ref->StoreType(); + + // TODO(crbug.com/tint/809): The originating variable of the left-hand side + // must not have an access(read) access attribute. + // https://gpuweb.github.io/gpuweb/wgsl/#assignment + + auto* storage_type = storage_type_with_access->UnwrapAccess(); + auto* value_type = rhs_type->UnwrapRef(); // Implicit load of RHS + + // RHS needs to be of a storable type + if (!IsStorable(value_type)) { + diagnostics_.add_error("'" + TypeNameOf(a->rhs()) + "' is not storable", + a->rhs()->source()); + return false; + } + + // Value type has to match storage type + if (storage_type != value_type) { + diagnostics_.add_error("cannot assign '" + TypeNameOf(a->rhs()) + "' to '" + + TypeNameOf(a->lhs()) + "'", + a->source()); + return false; + } + + return true; +} + bool Resolver::ApplyStorageClassUsageToType(ast::StorageClass sc, sem::Type* ty, const Source& usage) { - ty = const_cast(ty->UnwrapAccess()); + ty = const_cast(ty->UnwrapRef()); if (auto* str = ty->As()) { if (str->StorageClassUsage().count(sc)) { @@ -3079,23 +3125,15 @@ void Resolver::Mark(const ast::Node* node) { } Resolver::VariableInfo::VariableInfo(const ast::Variable* decl, - sem::Type* ctype, + sem::Type* ty, const std::string& tn, + ast::StorageClass sc, ast::AccessControl::Access ac) : declaration(decl), - type(ctype), + type(ty), type_name(tn), - storage_class(decl->declared_storage_class()), - access_control(ac) { - if (storage_class == ast::StorageClass::kNone && - type->UnwrapAll()->is_handle()) { - // https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables - // If the store type is a texture type or a sampler type, then the variable - // declaration must not have a storage class decoration. The storage class - // will always be handle. - storage_class = ast::StorageClass::kUniformConstant; - } -} + storage_class(sc), + access_control(ac) {} Resolver::VariableInfo::~VariableInfo() = default; diff --git a/src/resolver/resolver.h b/src/resolver/resolver.h index 3b8b05e9ab..76a722f281 100644 --- a/src/resolver/resolver.h +++ b/src/resolver/resolver.h @@ -79,13 +79,6 @@ class Resolver { /// @returns true if the given type is host-shareable bool IsHostShareable(const sem::Type* type); - /// @param lhs the assignment store type (non-pointer) - /// @param rhs the assignment source type (non-pointer or pointer with - /// auto-deref) - /// @returns true an expression of type `rhs` can be assigned to a variable, - /// structure member or array element of type `lhs` - static bool IsValidAssignment(const sem::Type* lhs, const sem::Type* rhs); - private: /// Structure holding semantic information about a variable. /// Used to build the sem::Variable nodes at the end of resolving. @@ -93,6 +86,7 @@ class Resolver { VariableInfo(const ast::Variable* decl, sem::Type* type, const std::string& type_name, + ast::StorageClass storage_class, ast::AccessControl::Access ac); ~VariableInfo(); @@ -139,6 +133,43 @@ class Resolver { sem::Statement* statement; }; + /// Structure holding semantic information about a block (i.e. scope), such as + /// parent block and variables declared in the block. + /// Used to validate variable scoping rules. + struct BlockInfo { + enum class Type { kGeneric, kLoop, kLoopContinuing, kSwitchCase }; + + BlockInfo(const ast::BlockStatement* block, Type type, BlockInfo* parent); + ~BlockInfo(); + + template + BlockInfo* FindFirstParent(Pred&& pred) { + BlockInfo* curr = this; + while (curr && !pred(curr)) { + curr = curr->parent; + } + return curr; + } + + BlockInfo* FindFirstParent(BlockInfo::Type ty) { + return FindFirstParent( + [ty](auto* block_info) { return block_info->type == ty; }); + } + + ast::BlockStatement const* const block; + Type const type; + BlockInfo* const parent; + std::vector decls; + + // first_continue is set to the index of the first variable in decls + // declared after the first continue statement in a loop block, if any. + constexpr static size_t kNoContinue = size_t(~0); + size_t first_continue = kNoContinue; + }; + + /// Describes the context in which a variable is declared + enum class VariableKind { kParameter, kLocal, kGlobal }; + /// Resolves the program, without creating final the semantic nodes. /// @returns true on success, false on error bool ResolveInternal(); @@ -207,6 +238,11 @@ class Resolver { bool ValidateStructure(const sem::Struct* str); bool ValidateSwitch(const ast::SwitchStatement* s); bool ValidateVariable(const VariableInfo* info); + bool ValidateVariableConstructor(const ast::Variable* var, + const sem::Type* storage_type, + const std::string& type_name, + const sem::Type* rhs_type, + const std::string& rhs_type_name); bool ValidateVectorConstructor(const ast::TypeConstructorExpression* ctor, const sem::Vector* vec_type); @@ -235,8 +271,8 @@ class Resolver { /// @note this method does not resolve the decorations as these are /// context-dependent (global, local, parameter) /// @param var the variable to create or return the `VariableInfo` for - /// @param is_parameter true if the variable represents a parameter - VariableInfo* Variable(ast::Variable* var, bool is_parameter); + /// @param kind what kind of variable we are declaring + VariableInfo* Variable(ast::Variable* var, VariableKind kind); /// Records the storage class usage for the given type, and any transient /// dependencies of the type. Validates that the type can be used for the diff --git a/src/resolver/resolver_test.cc b/src/resolver/resolver_test.cc index 330492e32b..e81be395d8 100644 --- a/src/resolver/resolver_test.cc +++ b/src/resolver/resolver_test.cc @@ -36,6 +36,7 @@ #include "src/sem/call.h" #include "src/sem/function.h" #include "src/sem/member_accessor_expression.h" +#include "src/sem/reference_type.h" #include "src/sem/sampled_texture_type.h" #include "src/sem/statement.h" #include "src/sem/variable.h" @@ -66,7 +67,7 @@ TEST_F(ResolverTest, Stmt_Assign) { ASSERT_NE(TypeOf(lhs), nullptr); ASSERT_NE(TypeOf(rhs), nullptr); - EXPECT_TRUE(TypeOf(lhs)->UnwrapAll()->Is()); + EXPECT_TRUE(TypeOf(lhs)->UnwrapRef()->Is()); EXPECT_TRUE(TypeOf(rhs)->Is()); EXPECT_EQ(StmtOf(lhs), assign); EXPECT_EQ(StmtOf(rhs), assign); @@ -90,7 +91,7 @@ TEST_F(ResolverTest, Stmt_Case) { ASSERT_NE(TypeOf(lhs), nullptr); ASSERT_NE(TypeOf(rhs), nullptr); - EXPECT_TRUE(TypeOf(lhs)->UnwrapAll()->Is()); + EXPECT_TRUE(TypeOf(lhs)->UnwrapRef()->Is()); EXPECT_TRUE(TypeOf(rhs)->Is()); EXPECT_EQ(StmtOf(lhs), assign); EXPECT_EQ(StmtOf(rhs), assign); @@ -110,7 +111,7 @@ TEST_F(ResolverTest, Stmt_Block) { ASSERT_NE(TypeOf(lhs), nullptr); ASSERT_NE(TypeOf(rhs), nullptr); - EXPECT_TRUE(TypeOf(lhs)->UnwrapAll()->Is()); + EXPECT_TRUE(TypeOf(lhs)->UnwrapRef()->Is()); EXPECT_TRUE(TypeOf(rhs)->Is()); EXPECT_EQ(StmtOf(lhs), assign); EXPECT_EQ(StmtOf(rhs), assign); @@ -147,9 +148,9 @@ TEST_F(ResolverTest, Stmt_If) { ASSERT_NE(TypeOf(lhs), nullptr); ASSERT_NE(TypeOf(rhs), nullptr); EXPECT_TRUE(TypeOf(stmt->condition())->Is()); - EXPECT_TRUE(TypeOf(else_lhs)->UnwrapAll()->Is()); + EXPECT_TRUE(TypeOf(else_lhs)->UnwrapRef()->Is()); EXPECT_TRUE(TypeOf(else_rhs)->Is()); - EXPECT_TRUE(TypeOf(lhs)->UnwrapAll()->Is()); + EXPECT_TRUE(TypeOf(lhs)->UnwrapRef()->Is()); EXPECT_TRUE(TypeOf(rhs)->Is()); EXPECT_EQ(StmtOf(lhs), assign); EXPECT_EQ(StmtOf(rhs), assign); @@ -180,9 +181,9 @@ TEST_F(ResolverTest, Stmt_Loop) { ASSERT_NE(TypeOf(body_rhs), nullptr); ASSERT_NE(TypeOf(continuing_lhs), nullptr); ASSERT_NE(TypeOf(continuing_rhs), nullptr); - EXPECT_TRUE(TypeOf(body_lhs)->UnwrapAll()->Is()); + EXPECT_TRUE(TypeOf(body_lhs)->UnwrapRef()->Is()); EXPECT_TRUE(TypeOf(body_rhs)->Is()); - EXPECT_TRUE(TypeOf(continuing_lhs)->UnwrapAll()->Is()); + EXPECT_TRUE(TypeOf(continuing_lhs)->UnwrapRef()->Is()); EXPECT_TRUE(TypeOf(continuing_rhs)->Is()); EXPECT_EQ(BlockOf(body_lhs), body); EXPECT_EQ(BlockOf(body_rhs), body); @@ -224,7 +225,7 @@ TEST_F(ResolverTest, Stmt_Switch) { ASSERT_NE(TypeOf(rhs), nullptr); EXPECT_TRUE(TypeOf(stmt->condition())->Is()); - EXPECT_TRUE(TypeOf(lhs)->UnwrapAll()->Is()); + EXPECT_TRUE(TypeOf(lhs)->UnwrapRef()->Is()); EXPECT_TRUE(TypeOf(rhs)->Is()); EXPECT_EQ(BlockOf(lhs), case_block); EXPECT_EQ(BlockOf(rhs), case_block); @@ -328,9 +329,9 @@ TEST_F(ResolverTest, Stmt_VariableDecl_OuterScopeAfterInnerScope) { ASSERT_NE(TypeOf(foo_f32_init), nullptr); EXPECT_TRUE(TypeOf(foo_f32_init)->Is()); ASSERT_NE(TypeOf(bar_i32_init), nullptr); - EXPECT_TRUE(TypeOf(bar_i32_init)->UnwrapAll()->Is()); + EXPECT_TRUE(TypeOf(bar_i32_init)->UnwrapRef()->Is()); ASSERT_NE(TypeOf(bar_f32_init), nullptr); - EXPECT_TRUE(TypeOf(bar_f32_init)->UnwrapAll()->Is()); + EXPECT_TRUE(TypeOf(bar_f32_init)->UnwrapRef()->Is()); EXPECT_EQ(StmtOf(foo_i32_init), foo_i32_decl); EXPECT_EQ(StmtOf(bar_i32_init), bar_i32_decl); EXPECT_EQ(StmtOf(foo_f32_init), foo_f32_decl); @@ -377,7 +378,7 @@ TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScopeAfterFunctionScope) { ASSERT_NE(TypeOf(fn_i32_init), nullptr); EXPECT_TRUE(TypeOf(fn_i32_init)->Is()); ASSERT_NE(TypeOf(fn_f32_init), nullptr); - EXPECT_TRUE(TypeOf(fn_f32_init)->UnwrapAll()->Is()); + EXPECT_TRUE(TypeOf(fn_f32_init)->UnwrapRef()->Is()); EXPECT_EQ(StmtOf(fn_i32_init), fn_i32_decl); EXPECT_EQ(StmtOf(mod_init), nullptr); EXPECT_EQ(StmtOf(fn_f32_init), fn_f32_decl); @@ -397,10 +398,10 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Array) { EXPECT_TRUE(r()->Resolve()) << r()->error(); ASSERT_NE(TypeOf(acc), nullptr); - ASSERT_TRUE(TypeOf(acc)->Is()); + ASSERT_TRUE(TypeOf(acc)->Is()); - auto* ptr = TypeOf(acc)->As(); - EXPECT_TRUE(ptr->StoreType()->Is()); + auto* ref = TypeOf(acc)->As(); + EXPECT_TRUE(ref->StoreType()->Is()); } TEST_F(ResolverTest, Expr_ArrayAccessor_Alias_Array) { @@ -415,10 +416,10 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Alias_Array) { EXPECT_TRUE(r()->Resolve()) << r()->error(); ASSERT_NE(TypeOf(acc), nullptr); - ASSERT_TRUE(TypeOf(acc)->Is()); + ASSERT_TRUE(TypeOf(acc)->Is()); - auto* ptr = TypeOf(acc)->As(); - EXPECT_TRUE(ptr->StoreType()->Is()); + auto* ref = TypeOf(acc)->As(); + EXPECT_TRUE(ref->StoreType()->Is()); } TEST_F(ResolverTest, Expr_ArrayAccessor_Array_Constant) { @@ -442,11 +443,11 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix) { EXPECT_TRUE(r()->Resolve()) << r()->error(); ASSERT_NE(TypeOf(acc), nullptr); - ASSERT_TRUE(TypeOf(acc)->Is()); + ASSERT_TRUE(TypeOf(acc)->Is()); - auto* ptr = TypeOf(acc)->As(); - ASSERT_TRUE(ptr->StoreType()->Is()); - EXPECT_EQ(ptr->StoreType()->As()->size(), 3u); + auto* ref = TypeOf(acc)->As(); + ASSERT_TRUE(ref->StoreType()->Is()); + EXPECT_EQ(ref->StoreType()->As()->size(), 3u); } TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix_BothDimensions) { @@ -458,10 +459,10 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix_BothDimensions) { EXPECT_TRUE(r()->Resolve()) << r()->error(); ASSERT_NE(TypeOf(acc), nullptr); - ASSERT_TRUE(TypeOf(acc)->Is()); + ASSERT_TRUE(TypeOf(acc)->Is()); - auto* ptr = TypeOf(acc)->As(); - EXPECT_TRUE(ptr->StoreType()->Is()); + auto* ref = TypeOf(acc)->As(); + EXPECT_TRUE(ref->StoreType()->Is()); } TEST_F(ResolverTest, Expr_ArrayAccessor_Vector) { @@ -473,10 +474,10 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Vector) { EXPECT_TRUE(r()->Resolve()) << r()->error(); ASSERT_NE(TypeOf(acc), nullptr); - ASSERT_TRUE(TypeOf(acc)->Is()); + ASSERT_TRUE(TypeOf(acc)->Is()); - auto* ptr = TypeOf(acc)->As(); - EXPECT_TRUE(ptr->StoreType()->Is()); + auto* ref = TypeOf(acc)->As(); + EXPECT_TRUE(ref->StoreType()->Is()); } TEST_F(ResolverTest, Expr_Bitcast) { @@ -519,7 +520,10 @@ TEST_F(ResolverTest, Expr_Call_InBinaryOp) { TEST_F(ResolverTest, Expr_Call_WithParams) { ast::VariableList params; - Func("my_func", params, ty.void_(), {}, ast::DecorationList{}); + Func("my_func", params, ty.f32(), + { + Return(1.2f), + }); auto* param = Expr(2.4f); @@ -609,8 +613,8 @@ TEST_F(ResolverTest, Expr_Identifier_GlobalVariable) { EXPECT_TRUE(r()->Resolve()) << r()->error(); ASSERT_NE(TypeOf(ident), nullptr); - EXPECT_TRUE(TypeOf(ident)->Is()); - EXPECT_TRUE(TypeOf(ident)->As()->StoreType()->Is()); + ASSERT_TRUE(TypeOf(ident)->Is()); + EXPECT_TRUE(TypeOf(ident)->UnwrapRef()->Is()); EXPECT_TRUE(CheckVarUsers(my_var, {ident})); ASSERT_NE(VarOf(ident), nullptr); EXPECT_EQ(VarOf(ident)->Declaration(), my_var); @@ -674,14 +678,12 @@ TEST_F(ResolverTest, Expr_Identifier_FunctionVariable) { EXPECT_TRUE(r()->Resolve()) << r()->error(); ASSERT_NE(TypeOf(my_var_a), nullptr); - EXPECT_TRUE(TypeOf(my_var_a)->Is()); - EXPECT_TRUE( - TypeOf(my_var_a)->As()->StoreType()->Is()); + ASSERT_TRUE(TypeOf(my_var_a)->Is()); + EXPECT_TRUE(TypeOf(my_var_a)->UnwrapRef()->Is()); EXPECT_EQ(StmtOf(my_var_a), assign); ASSERT_NE(TypeOf(my_var_b), nullptr); - EXPECT_TRUE(TypeOf(my_var_b)->Is()); - EXPECT_TRUE( - TypeOf(my_var_b)->As()->StoreType()->Is()); + ASSERT_TRUE(TypeOf(my_var_b)->Is()); + EXPECT_TRUE(TypeOf(my_var_b)->UnwrapRef()->Is()); EXPECT_EQ(StmtOf(my_var_b), assign); EXPECT_TRUE(CheckVarUsers(var, {my_var_a, my_var_b})); ASSERT_NE(VarOf(my_var_a), nullptr); @@ -691,29 +693,30 @@ TEST_F(ResolverTest, Expr_Identifier_FunctionVariable) { } TEST_F(ResolverTest, Expr_Identifier_Function_Ptr) { - auto* my_var_a = Expr("my_var"); - auto* my_var_b = Expr("my_var"); - auto* assign = Assign(my_var_a, my_var_b); - + auto* v = Expr("v"); + auto* p = Expr("p"); + auto* v_decl = Decl(Var("v", ty.f32())); + auto* p_decl = Decl( + Const("p", ty.pointer(ast::StorageClass::kFunction), AddressOf(v))); + auto* assign = Assign(Deref(p), 1.23f); Func("my_func", ast::VariableList{}, ty.void_(), { - Decl(Var("my_var", ty.pointer(ast::StorageClass::kFunction))), + v_decl, + p_decl, assign, }, ast::DecorationList{}); EXPECT_TRUE(r()->Resolve()) << r()->error(); - ASSERT_NE(TypeOf(my_var_a), nullptr); - EXPECT_TRUE(TypeOf(my_var_a)->Is()); - EXPECT_TRUE( - TypeOf(my_var_a)->As()->StoreType()->Is()); - EXPECT_EQ(StmtOf(my_var_a), assign); - ASSERT_NE(TypeOf(my_var_b), nullptr); - EXPECT_TRUE(TypeOf(my_var_b)->Is()); - EXPECT_TRUE( - TypeOf(my_var_b)->As()->StoreType()->Is()); - EXPECT_EQ(StmtOf(my_var_b), assign); + ASSERT_NE(TypeOf(v), nullptr); + ASSERT_TRUE(TypeOf(v)->Is()); + EXPECT_TRUE(TypeOf(v)->UnwrapRef()->Is()); + EXPECT_EQ(StmtOf(v), p_decl); + ASSERT_NE(TypeOf(p), nullptr); + ASSERT_TRUE(TypeOf(p)->Is()); + EXPECT_TRUE(TypeOf(p)->UnwrapPtr()->Is()); + EXPECT_EQ(StmtOf(p), assign); } TEST_F(ResolverTest, Expr_Call_Function) { @@ -895,10 +898,10 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct) { EXPECT_TRUE(r()->Resolve()) << r()->error(); ASSERT_NE(TypeOf(mem), nullptr); - ASSERT_TRUE(TypeOf(mem)->Is()); + ASSERT_TRUE(TypeOf(mem)->Is()); - auto* ptr = TypeOf(mem)->As(); - EXPECT_TRUE(ptr->StoreType()->Is()); + auto* ref = TypeOf(mem)->As(); + EXPECT_TRUE(ref->StoreType()->Is()); auto* sma = Sem().Get(mem)->As(); ASSERT_NE(sma, nullptr); EXPECT_EQ(sma->Member()->Type(), ty.f32()); @@ -920,10 +923,10 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) { EXPECT_TRUE(r()->Resolve()) << r()->error(); ASSERT_NE(TypeOf(mem), nullptr); - ASSERT_TRUE(TypeOf(mem)->Is()); + ASSERT_TRUE(TypeOf(mem)->Is()); - auto* ptr = TypeOf(mem)->As(); - EXPECT_TRUE(ptr->StoreType()->Is()); + auto* ref = TypeOf(mem)->As(); + EXPECT_TRUE(ref->StoreType()->Is()); auto* sma = Sem().Get(mem)->As(); ASSERT_NE(sma, nullptr); EXPECT_EQ(sma->Member()->Type(), ty.f32()); @@ -956,10 +959,10 @@ TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle_SingleElement) { EXPECT_TRUE(r()->Resolve()) << r()->error(); ASSERT_NE(TypeOf(mem), nullptr); - ASSERT_TRUE(TypeOf(mem)->Is()); + ASSERT_TRUE(TypeOf(mem)->Is()); - auto* ptr = TypeOf(mem)->As(); - ASSERT_TRUE(ptr->StoreType()->Is()); + auto* ref = TypeOf(mem)->As(); + ASSERT_TRUE(ref->StoreType()->Is()); ASSERT_TRUE(Sem().Get(mem)->Is()); EXPECT_THAT(Sem().Get(mem)->As()->Indices(), ElementsAre(2)); } diff --git a/src/resolver/type_constructor_validation_test.cc b/src/resolver/type_constructor_validation_test.cc index e5d06d0aa9..94fc5ee058 100644 --- a/src/resolver/type_constructor_validation_test.cc +++ b/src/resolver/type_constructor_validation_test.cc @@ -13,6 +13,7 @@ // limitations under the License. #include "src/resolver/resolver_test_helper.h" +#include "src/sem/reference_type.h" namespace tint { namespace resolver { @@ -51,13 +52,19 @@ TEST_F(ResolverTypeConstructorValidationTest, InferTypeTest_Simple) { auto* a_ident = Expr("a"); auto* b_ident = Expr("b"); - WrapInFunction(Decl(a), Decl(b), Assign(a_ident, "a"), Assign(b_ident, "b")); + WrapInFunction(a, b, Assign(a_ident, "a"), Assign(b_ident, "b")); ASSERT_TRUE(r()->Resolve()) << r()->error(); - ASSERT_EQ(TypeOf(a_ident), - ty.pointer(ty.i32(), ast::StorageClass::kFunction)); - ASSERT_EQ(TypeOf(b_ident), - ty.pointer(ty.i32(), ast::StorageClass::kFunction)); + ASSERT_TRUE(TypeOf(a_ident)->Is()); + EXPECT_TRUE( + TypeOf(a_ident)->As()->StoreType()->Is()); + EXPECT_EQ(TypeOf(a_ident)->As()->StorageClass(), + ast::StorageClass::kFunction); + ASSERT_TRUE(TypeOf(b_ident)->Is()); + EXPECT_TRUE( + TypeOf(b_ident)->As()->StoreType()->Is()); + EXPECT_EQ(TypeOf(b_ident)->As()->StorageClass(), + ast::StorageClass::kFunction); } using InferTypeTest_FromConstructorExpression = ResolverTestWithParam; @@ -79,9 +86,8 @@ TEST_P(InferTypeTest_FromConstructorExpression, All) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* got = TypeOf(a_ident); - auto* expected = - ty.pointer(params.create_rhs_sem_type(ty), ast::StorageClass::kFunction) - .sem; + auto* expected = create(params.create_rhs_sem_type(ty), + ast::StorageClass::kFunction); ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n" << "expected: " << FriendlyName(expected) << "\n"; } @@ -134,9 +140,8 @@ TEST_P(InferTypeTest_FromArithmeticExpression, All) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* got = TypeOf(a_ident); - auto* expected = - ty.pointer(params.create_rhs_sem_type(ty), ast::StorageClass::kFunction) - .sem; + auto* expected = create(params.create_rhs_sem_type(ty), + ast::StorageClass::kFunction); ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n" << "expected: " << FriendlyName(expected) << "\n"; } @@ -184,9 +189,8 @@ TEST_P(InferTypeTest_FromCallExpression, All) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* got = TypeOf(a_ident); - auto* expected = - ty.pointer(params.create_rhs_sem_type(ty), ast::StorageClass::kFunction) - .sem; + auto* expected = create(params.create_rhs_sem_type(ty), + ast::StorageClass::kFunction); ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n" << "expected: " << FriendlyName(expected) << "\n"; } diff --git a/src/resolver/type_validation_test.cc b/src/resolver/type_validation_test.cc index beec7d54bd..de11bb9266 100644 --- a/src/resolver/type_validation_test.cc +++ b/src/resolver/type_validation_test.cc @@ -49,27 +49,6 @@ TEST_F(ResolverTypeValidationTest, VariableDeclNoConstructor_Pass) { ASSERT_NE(TypeOf(rhs), nullptr); } -TEST_F(ResolverTypeValidationTest, FunctionConstantNoConstructor_Fail) { - // { - // let a :i32; - // } - auto* var = Const(Source{{12, 34}}, "a", ty.i32(), nullptr); - WrapInFunction(var); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: let declarations must have initializers"); -} - -TEST_F(ResolverTypeValidationTest, GlobalConstantNoConstructor_Fail) { - // let a :i32; - GlobalConst(Source{{12, 34}}, "a", ty.i32(), nullptr); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: let declarations must have initializers"); -} - TEST_F(ResolverTypeValidationTest, GlobalConstantNoConstructor_Pass) { // [[override(0)]] let a :i32; GlobalConst(Source{{12, 34}}, "a", ty.i32(), nullptr, @@ -117,19 +96,6 @@ TEST_F(ResolverTypeValidationTest, GlobalVariableUnique_Pass) { EXPECT_TRUE(r()->Resolve()) << r()->error(); } -TEST_F(ResolverTypeValidationTest, GlobalVariableNotUnique_Fail) { - // var global_var : f32 = 0.1; - // var global_var : i32 = 0; - Global("global_var", ty.f32(), ast::StorageClass::kPrivate, Expr(0.1f)); - - Global(Source{{12, 34}}, "global_var", ty.i32(), ast::StorageClass::kPrivate, - Expr(0)); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error v-0011: redeclared global identifier 'global_var'"); -} - TEST_F(ResolverTypeValidationTest, GlobalVariableFunctionVariableNotUnique_Pass) { // fn my_func() { @@ -146,48 +112,6 @@ TEST_F(ResolverTypeValidationTest, EXPECT_TRUE(r()->Resolve()) << r()->error(); } -TEST_F(ResolverTypeValidationTest, - GlobalVariableFunctionVariableNotUnique_Fail) { - // var a: f32 = 2.1; - // fn my_func() { - // var a: f32 = 2.0; - // return 0; - // } - - Global("a", ty.f32(), ast::StorageClass::kPrivate, Expr(2.1f)); - - auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(2.0f)); - - Func("my_func", ast::VariableList{}, ty.void_(), - ast::StatementList{ - Decl(Source{{12, 34}}, var), - }, - ast::DecorationList{}); - - EXPECT_FALSE(r()->Resolve()) << r()->error(); - EXPECT_EQ(r()->error(), "12:34 error v-0013: redeclared identifier 'a'"); -} - -TEST_F(ResolverTypeValidationTest, RedeclaredIdentifier_Fail) { - // fn my_func()() { - // var a :i32 = 2; - // var a :f21 = 2.0; - // } - auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)); - - auto* var_a_float = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(0.1f)); - - Func("my_func", ast::VariableList{}, ty.void_(), - ast::StatementList{ - Decl(var), - Decl(Source{{12, 34}}, var_a_float), - }, - ast::DecorationList{}); - - EXPECT_FALSE(r()->Resolve()) << r()->error(); - EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'a'"); -} - TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierInnerScope_Pass) { // { // if (true) { var a : f32 = 2.0; } @@ -209,31 +133,6 @@ TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierInnerScope_Pass) { EXPECT_TRUE(r()->Resolve()); } -TEST_F(ResolverTypeValidationTest, - DISABLED_RedeclaredIdentifierInnerScope_False) { - // TODO(sarahM0): remove DISABLED after implementing ValidateIfStatement - // and it should just work - // { - // var a : f32 = 3.14; - // if (true) { var a : f32 = 2.0; } - // } - auto* var_a_float = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(3.1f)); - - auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(2.0f)); - - auto* cond = Expr(true); - auto* body = Block(Decl(Source{{12, 34}}, var)); - - auto* outer_body = - Block(Decl(var_a_float), - create(cond, body, ast::ElseStatementList{})); - - WrapInFunction(outer_body); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'a'"); -} - TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierInnerScopeBlock_Pass) { // { // { var a : f32; } @@ -250,23 +149,6 @@ TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierInnerScopeBlock_Pass) { EXPECT_TRUE(r()->Resolve()) << r()->error(); } -TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierInnerScopeBlock_Fail) { - // { - // var a : f32; - // { var a : f32; } - // } - auto* var_inner = Var("a", ty.f32(), ast::StorageClass::kNone); - auto* inner = Block(Decl(Source{{12, 34}}, var_inner)); - - auto* var_outer = Var("a", ty.f32(), ast::StorageClass::kNone); - auto* outer_body = Block(Decl(var_outer), inner); - - WrapInFunction(outer_body); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'a'"); -} - TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierDifferentFunctions_Pass) { // func0 { var a : f32 = 2.0; return; } @@ -519,7 +401,7 @@ TEST_P(CanonicalTest, All) { EXPECT_TRUE(r()->Resolve()) << r()->error(); - auto* got = TypeOf(expr)->UnwrapPtr(); + auto* got = TypeOf(expr)->UnwrapRef(); auto* expected = params.create_sem_type(ty); EXPECT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n" diff --git a/src/resolver/validation_test.cc b/src/resolver/validation_test.cc index 9440f1f560..ed4d08992d 100644 --- a/src/resolver/validation_test.cc +++ b/src/resolver/validation_test.cc @@ -160,34 +160,6 @@ TEST_F(ResolverValidationTest, Stmt_Else_NonBool) { "12:34 error: else statement condition must be bool, got f32"); } -TEST_F(ResolverValidationTest, - Stmt_VariableDecl_MismatchedTypeScalarConstructor) { - u32 unsigned_value = 2u; // Type does not match variable type - auto* decl = Decl(Var(Source{{3, 3}}, "my_var", ty.i32(), - ast::StorageClass::kNone, Expr(unsigned_value))); - WrapInFunction(decl); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - R"(3:3 error: variable of type 'i32' cannot be initialized with a value of type 'u32')"); -} - -TEST_F(ResolverValidationTest, - Stmt_VariableDecl_MismatchedTypeScalarConstructor_Alias) { - auto* my_int = ty.alias("MyInt", ty.i32()); - AST().AddConstructedType(my_int); - u32 unsigned_value = 2u; // Type does not match variable type - auto* decl = Decl(Var(Source{{3, 3}}, "my_var", my_int, - ast::StorageClass::kNone, Expr(unsigned_value))); - WrapInFunction(decl); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - R"(3:3 error: variable of type 'MyInt' cannot be initialized with a value of type 'u32')"); -} - TEST_F(ResolverValidationTest, Expr_Error_Unknown) { auto* e = create(Source{Source::Location{2, 30}}); WrapInFunction(e); diff --git a/src/resolver/var_let_test.cc b/src/resolver/var_let_test.cc new file mode 100644 index 0000000000..bf37ace490 --- /dev/null +++ b/src/resolver/var_let_test.cc @@ -0,0 +1,133 @@ +// 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/resolver/resolver.h" +#include "src/resolver/resolver_test_helper.h" +#include "src/sem/reference_type.h" + +#include "gmock/gmock.h" + +namespace tint { +namespace resolver { +namespace { + +struct ResolverVarLetTest : public resolver::TestHelper, + public testing::Test {}; + +TEST_F(ResolverVarLetTest, TypeOfVar) { + // struct S { i : i32; } + // alias A = S; + // fn F(){ + // var i : i32; + // var u : u32; + // var f : f32; + // var b : bool; + // var s : S; + // var a : A; + // } + + auto* S = Structure("S", {Member("i", ty.i32())}); + auto* A = ty.alias("A", S); + AST().AddConstructedType(A); + + auto* i = Var("i", ty.i32(), ast::StorageClass::kNone); + auto* u = Var("u", ty.u32(), ast::StorageClass::kNone); + auto* f = Var("f", ty.f32(), ast::StorageClass::kNone); + auto* b = Var("b", ty.bool_(), ast::StorageClass::kNone); + auto* s = Var("s", S, ast::StorageClass::kNone); + auto* a = Var("a", A, ast::StorageClass::kNone); + + Func("F", {}, ty.void_(), + { + Decl(i), + Decl(u), + Decl(f), + Decl(b), + Decl(s), + Decl(a), + }); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + // `var` declarations are always of reference type + ASSERT_TRUE(TypeOf(i)->Is()); + ASSERT_TRUE(TypeOf(u)->Is()); + ASSERT_TRUE(TypeOf(f)->Is()); + ASSERT_TRUE(TypeOf(b)->Is()); + ASSERT_TRUE(TypeOf(s)->Is()); + ASSERT_TRUE(TypeOf(a)->Is()); + + EXPECT_TRUE(TypeOf(i)->As()->StoreType()->Is()); + EXPECT_TRUE(TypeOf(u)->As()->StoreType()->Is()); + EXPECT_TRUE(TypeOf(f)->As()->StoreType()->Is()); + EXPECT_TRUE(TypeOf(b)->As()->StoreType()->Is()); + EXPECT_TRUE(TypeOf(s)->As()->StoreType()->Is()); + EXPECT_TRUE(TypeOf(a)->As()->StoreType()->Is()); +} + +TEST_F(ResolverVarLetTest, TypeOfLet) { + // struct S { i : i32; } + // fn F(){ + // var v : i32; + // let i : i32 = 1; + // let u : u32 = 1u; + // let f : f32 = 1.; + // let b : bool = true; + // let s : S = S(1); + // let a : A = A(1); + // let p : pointer = &V; + // } + + auto* S = Structure("S", {Member("i", ty.i32())}); + auto* A = ty.alias("A", S); + AST().AddConstructedType(A); + + auto* v = Var("v", ty.i32(), ast::StorageClass::kNone); + auto* i = Const("i", ty.i32(), Expr(1)); + auto* u = Const("u", ty.u32(), Expr(1u)); + auto* f = Const("f", ty.f32(), Expr(1.f)); + auto* b = Const("b", ty.bool_(), Expr(true)); + auto* s = Const("s", S, Construct(S, Expr(1))); + auto* a = Const("a", A, Construct(A, Expr(1))); + auto* p = + Const("p", ty.pointer(ast::StorageClass::kFunction), AddressOf(v)); + + Func("F", {}, ty.void_(), + { + Decl(v), + Decl(i), + Decl(u), + Decl(f), + Decl(b), + Decl(s), + Decl(a), + Decl(p), + }); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + // `let` declarations are always of the storage type + EXPECT_TRUE(TypeOf(i)->Is()); + EXPECT_TRUE(TypeOf(u)->Is()); + EXPECT_TRUE(TypeOf(f)->Is()); + EXPECT_TRUE(TypeOf(b)->Is()); + EXPECT_TRUE(TypeOf(s)->Is()); + EXPECT_TRUE(TypeOf(a)->Is()); + ASSERT_TRUE(TypeOf(p)->Is()); + EXPECT_TRUE(TypeOf(p)->As()->StoreType()->Is()); +} + +} // namespace +} // namespace resolver +} // namespace tint diff --git a/src/resolver/var_let_validation_test.cc b/src/resolver/var_let_validation_test.cc new file mode 100644 index 0000000000..23c42e9e6d --- /dev/null +++ b/src/resolver/var_let_validation_test.cc @@ -0,0 +1,220 @@ +// 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/resolver/resolver.h" +#include "src/resolver/resolver_test_helper.h" + +#include "gmock/gmock.h" + +namespace tint { +namespace resolver { +namespace { + +struct ResolverVarLetValidationTest : public resolver::TestHelper, + public testing::Test {}; + +TEST_F(ResolverVarLetValidationTest, LetNoInitializer) { + // let a : i32; + WrapInFunction(Const(Source{{12, 34}}, "a", ty.i32(), nullptr)); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: let declarations must have initializers"); +} + +TEST_F(ResolverVarLetValidationTest, GlobalLetNoInitializer) { + // let a : i32; + GlobalConst(Source{{12, 34}}, "a", ty.i32(), nullptr); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: let declarations must have initializers"); +} + +TEST_F(ResolverVarLetValidationTest, VarConstructorNotStorable) { + // var i : i32; + // var p : pointer = &v; + auto* i = Var("i", ty.i32(), ast::StorageClass::kNone); + auto* p = Var("a", ty.i32(), ast::StorageClass::kNone, + AddressOf(Source{{12, 34}}, "i")); + WrapInFunction(i, p); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: 'ptr' is not storable for assignment"); +} + +TEST_F(ResolverVarLetValidationTest, LetConstructorWrongType) { + // var v : i32 = 2u + WrapInFunction(Const(Source{{3, 3}}, "v", ty.i32(), Expr(2u))); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + R"(3:3 error: cannot initialize let of type 'i32' with value of type 'u32')"); +} + +TEST_F(ResolverVarLetValidationTest, VarConstructorWrongType) { + // var v : i32 = 2u + WrapInFunction( + Var(Source{{3, 3}}, "v", ty.i32(), ast::StorageClass::kNone, Expr(2u))); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + R"(3:3 error: cannot initialize var of type 'i32' with value of type 'u32')"); +} + +TEST_F(ResolverVarLetValidationTest, LetConstructorWrongTypeViaAlias) { + auto* a = ty.alias("I32", ty.i32()); + AST().AddConstructedType(a); + WrapInFunction(Const(Source{{3, 3}}, "v", a, Expr(2u))); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + R"(3:3 error: cannot initialize let of type 'I32' with value of type 'u32')"); +} + +TEST_F(ResolverVarLetValidationTest, VarConstructorWrongTypeViaAlias) { + auto* a = ty.alias("I32", ty.i32()); + AST().AddConstructedType(a); + WrapInFunction( + Var(Source{{3, 3}}, "v", a, ast::StorageClass::kNone, Expr(2u))); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + R"(3:3 error: cannot initialize var of type 'I32' with value of type 'u32')"); +} + +TEST_F(ResolverVarLetValidationTest, LetOfPtrConstructedWithRef) { + // var a : f32; + // let b : ptr = a; + const auto priv = ast::StorageClass::kFunction; + auto* var_a = Var("a", ty.f32(), priv); + auto* var_b = + Const(Source{{12, 34}}, "b", ty.pointer(priv), Expr("a"), {}); + WrapInFunction(var_a, var_b); + + ASSERT_FALSE(r()->Resolve()); + + EXPECT_EQ( + r()->error(), + R"(12:34 error: cannot initialize let of type 'ptr' with value of type 'f32')"); +} + +TEST_F(ResolverVarLetValidationTest, LocalVarRedeclared) { + // var v : f32; + // var v : i32; + auto* v1 = Var("v", ty.f32(), ast::StorageClass::kNone); + auto* v2 = Var(Source{{12, 34}}, "v", ty.i32(), ast::StorageClass::kNone); + WrapInFunction(v1, v2); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'v'"); +} + +TEST_F(ResolverVarLetValidationTest, LocalLetRedeclared) { + // let l : f32 = 1.; + // let l : i32 = 0; + auto* l1 = Const("l", ty.f32(), Expr(1.f)); + auto* l2 = Const(Source{{12, 34}}, "l", ty.i32(), Expr(0)); + WrapInFunction(l1, l2); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'l'"); +} + +TEST_F(ResolverVarLetValidationTest, GlobalVarRedeclared) { + // var v : f32; + // var v : i32; + Global("v", ty.f32(), ast::StorageClass::kPrivate); + Global(Source{{12, 34}}, "v", ty.i32(), ast::StorageClass::kPrivate); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error v-0011: redeclared global identifier 'v'"); +} + +TEST_F(ResolverVarLetValidationTest, GlobalLetRedeclared) { + // let l : f32 = 0.1; + // let l : i32 = 0; + GlobalConst("l", ty.f32(), Expr(0.1f)); + GlobalConst(Source{{12, 34}}, "l", ty.i32(), Expr(0)); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error v-0011: redeclared global identifier 'l'"); +} + +TEST_F(ResolverVarLetValidationTest, GlobalVarRedeclaredAsLocal) { + // var v : f32 = 2.1; + // fn my_func() { + // var v : f32 = 2.0; + // return 0; + // } + + Global("v", ty.f32(), ast::StorageClass::kPrivate, Expr(2.1f)); + + WrapInFunction(Var(Source{{12, 34}}, "v", ty.f32(), ast::StorageClass::kNone, + Expr(2.0f))); + + EXPECT_FALSE(r()->Resolve()) << r()->error(); + EXPECT_EQ(r()->error(), "12:34 error v-0013: redeclared identifier 'v'"); +} + +TEST_F(ResolverVarLetValidationTest, VarRedeclaredInInnerBlock) { + // { + // var v : f32; + // { var v : f32; } + // } + auto* var_outer = Var("v", ty.f32(), ast::StorageClass::kNone); + auto* var_inner = + Var(Source{{12, 34}}, "v", ty.f32(), ast::StorageClass::kNone); + auto* inner = Block(Decl(var_inner)); + auto* outer_body = Block(Decl(var_outer), inner); + + WrapInFunction(outer_body); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'v'"); +} + +TEST_F(ResolverVarLetValidationTest, VarRedeclaredInIfBlock) { + // { + // var v : f32 = 3.14; + // if (true) { var v : f32 = 2.0; } + // } + auto* var_a_float = Var("v", ty.f32(), ast::StorageClass::kNone, Expr(3.1f)); + + auto* var = Var(Source{{12, 34}}, "v", ty.f32(), ast::StorageClass::kNone, + Expr(2.0f)); + + auto* cond = Expr(true); + auto* body = Block(Decl(var)); + + auto* outer_body = + Block(Decl(var_a_float), + create(cond, body, ast::ElseStatementList{})); + + WrapInFunction(outer_body); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'v'"); +} + +} // namespace +} // namespace resolver +} // namespace tint diff --git a/src/sem/function.cc b/src/sem/function.cc index 35c2e713e8..0c5e8443ca 100644 --- a/src/sem/function.cc +++ b/src/sem/function.cc @@ -139,7 +139,7 @@ Function::VariableBindings Function::ReferencedStorageTextureVariables() const { VariableBindings ret; for (auto* var : ReferencedModuleVariables()) { - auto* unwrapped_type = var->Type()->UnwrapAccess(); + auto* unwrapped_type = var->Type()->UnwrapRef(); auto* storage_texture = unwrapped_type->As(); if (storage_texture == nullptr) { continue; @@ -156,7 +156,7 @@ Function::VariableBindings Function::ReferencedDepthTextureVariables() const { VariableBindings ret; for (auto* var : ReferencedModuleVariables()) { - auto* unwrapped_type = var->Type()->UnwrapAccess(); + auto* unwrapped_type = var->Type()->UnwrapRef(); auto* storage_texture = unwrapped_type->As(); if (storage_texture == nullptr) { continue; @@ -174,7 +174,7 @@ Function::VariableBindings Function::ReferencedExternalTextureVariables() VariableBindings ret; for (auto* var : ReferencedModuleVariables()) { - auto* unwrapped_type = var->Type()->UnwrapAccess(); + auto* unwrapped_type = var->Type()->UnwrapRef(); auto* external_texture = unwrapped_type->As(); if (external_texture == nullptr) { continue; @@ -201,7 +201,7 @@ Function::VariableBindings Function::ReferencedSamplerVariablesImpl( VariableBindings ret; for (auto* var : ReferencedModuleVariables()) { - auto* unwrapped_type = var->Type()->UnwrapAccess(); + auto* unwrapped_type = var->Type()->UnwrapRef(); auto* sampler = unwrapped_type->As(); if (sampler == nullptr || sampler->kind() != kind) { continue; @@ -219,7 +219,7 @@ Function::VariableBindings Function::ReferencedSampledTextureVariablesImpl( VariableBindings ret; for (auto* var : ReferencedModuleVariables()) { - auto* unwrapped_type = var->Type()->UnwrapAccess(); + auto* unwrapped_type = var->Type()->UnwrapRef(); auto* texture = unwrapped_type->As(); if (texture == nullptr) { continue; diff --git a/src/sem/type.cc b/src/sem/type.cc index 1f7ffca602..00f9e10016 100644 --- a/src/sem/type.cc +++ b/src/sem/type.cc @@ -19,6 +19,7 @@ #include "src/sem/i32_type.h" #include "src/sem/matrix_type.h" #include "src/sem/pointer_type.h" +#include "src/sem/reference_type.h" #include "src/sem/sampler_type.h" #include "src/sem/texture_type.h" #include "src/sem/u32_type.h" @@ -43,21 +44,17 @@ const Type* Type::UnwrapPtr() const { return type; } -const Type* Type::UnwrapAccess() const { - // TODO(amaiorano): Delete this function +const Type* Type::UnwrapRef() const { auto* type = this; + if (auto* ref = type->As()) { + type = ref->StoreType(); + } return type; } -const Type* Type::UnwrapAll() const { +const Type* Type::UnwrapAccess() const { + // TODO(amaiorano): Delete this function auto* type = this; - while (true) { - if (auto* ptr = type->As()) { - type = ptr->StoreType(); - } else { - break; - } - } return type; } diff --git a/src/sem/type.h b/src/sem/type.h index 76a64e1d31..11dd0804b9 100644 --- a/src/sem/type.h +++ b/src/sem/type.h @@ -49,15 +49,13 @@ class Type : public Castable { /// otherwise const Type* UnwrapPtr() const; + /// @returns the inner type if this is a reference, `this` otherwise + const Type* UnwrapRef() const; + /// @returns the inner most type if this is an access control, `this` /// otherwise const Type* UnwrapAccess() const; - /// Returns the type found after removing all layers of access control and - /// pointer - /// @returns the unwrapped type - const Type* UnwrapAll() const; - /// @returns true if this type is a scalar bool is_scalar() const; /// @returns true if this type is a numeric scalar diff --git a/src/transform/binding_remapper.cc b/src/transform/binding_remapper.cc index 8a1c42cb47..f89bfd9d98 100644 --- a/src/transform/binding_remapper.cc +++ b/src/transform/binding_remapper.cc @@ -113,7 +113,7 @@ Output BindingRemapper::Run(const Program* in, const DataMap& datamap) { auto ac_it = remappings->access_controls.find(from); if (ac_it != remappings->access_controls.end()) { ast::AccessControl::Access ac = ac_it->second; - auto* ty = in->Sem().Get(var)->Type(); + auto* ty = in->Sem().Get(var)->Type()->UnwrapRef(); ast::Type* inner_ty = CreateASTTypeFor(&ctx, ty); auto* new_ty = ctx.dst->create(ac, inner_ty); auto* new_var = ctx.dst->create( diff --git a/src/transform/bound_array_accessors.cc b/src/transform/bound_array_accessors.cc index 82c221b4ad..19a9643a37 100644 --- a/src/transform/bound_array_accessors.cc +++ b/src/transform/bound_array_accessors.cc @@ -41,7 +41,7 @@ ast::ArrayAccessorExpression* BoundArrayAccessors::Transform( CloneContext* ctx) { auto& diags = ctx->dst->Diagnostics(); - auto* ret_type = ctx->src->Sem().Get(expr->array())->Type()->UnwrapAll(); + auto* ret_type = ctx->src->Sem().Get(expr->array())->Type()->UnwrapRef(); if (!ret_type->Is() && !ret_type->Is() && !ret_type->Is()) { return nullptr; diff --git a/src/transform/bound_array_accessors_test.cc b/src/transform/bound_array_accessors_test.cc index 00414f1890..b9120d4917 100644 --- a/src/transform/bound_array_accessors_test.cc +++ b/src/transform/bound_array_accessors_test.cc @@ -29,7 +29,7 @@ var a : array; let c : u32 = 1u; fn f() { - let b : ptr = a[c]; + let b : f32 = a[c]; } )"; @@ -39,7 +39,7 @@ var a : array; let c : u32 = 1u; fn f() { - let b : ptr = a[min(u32(c), 2u)]; + let b : f32 = a[min(u32(c), 2u)]; } )"; diff --git a/src/transform/calculate_array_length.cc b/src/transform/calculate_array_length.cc index 96efb9d263..e6becb424f 100644 --- a/src/transform/calculate_array_length.cc +++ b/src/transform/calculate_array_length.cc @@ -142,7 +142,7 @@ Output CalculateArrayLength::Run(const Program* in, const DataMap&) { auto* storage_buffer_expr = accessor->structure(); auto* storage_buffer_sem = sem.Get(storage_buffer_expr); auto* storage_buffer_type = - storage_buffer_sem->Type()->UnwrapAll()->As(); + storage_buffer_sem->Type()->UnwrapRef()->As(); // Generate BufferSizeIntrinsic for this storage type if we haven't // already diff --git a/src/transform/canonicalize_entry_point_io.cc b/src/transform/canonicalize_entry_point_io.cc index 8da983fbcf..bb1cb71692 100644 --- a/src/transform/canonicalize_entry_point_io.cc +++ b/src/transform/canonicalize_entry_point_io.cc @@ -115,7 +115,7 @@ Output CanonicalizeEntryPointIO::Run(const Program* in, const DataMap&) { // Pull out all struct members and build initializer list. std::vector member_names; for (auto* member : str->Members()) { - if (member->Type()->UnwrapAll()->Is()) { + if (member->Type()->Is()) { TINT_ICE(ctx.dst->Diagnostics()) << "nested pipeline IO struct"; } @@ -205,7 +205,7 @@ Output CanonicalizeEntryPointIO::Run(const Program* in, const DataMap&) { if (auto* str = ret_type->As()) { // Rebuild struct with only the entry point IO attributes. for (auto* member : str->Members()) { - if (member->Type()->UnwrapAll()->Is()) { + if (member->Type()->Is()) { TINT_ICE(ctx.dst->Diagnostics()) << "nested pipeline IO struct"; } diff --git a/src/transform/decompose_storage_access.cc b/src/transform/decompose_storage_access.cc index ab256a216e..46495a1237 100644 --- a/src/transform/decompose_storage_access.cc +++ b/src/transform/decompose_storage_access.cc @@ -29,6 +29,7 @@ #include "src/sem/array.h" #include "src/sem/call.h" #include "src/sem/member_accessor_expression.h" +#include "src/sem/reference_type.h" #include "src/sem/struct.h" #include "src/sem/variable.h" #include "src/utils/get_or_create.h" @@ -56,7 +57,7 @@ struct OffsetExpr : Offset { explicit OffsetExpr(ast::Expression* e) : expr(e) {} ast::Expression* Build(CloneContext& ctx) override { - auto* type = ctx.src->Sem().Get(expr)->Type()->UnwrapAll(); + auto* type = ctx.src->Sem().Get(expr)->Type()->UnwrapRef(); auto* res = ctx.Clone(expr); if (!type->Is()) { res = ctx.dst->Construct(res); @@ -333,8 +334,8 @@ void InsertGlobal(CloneContext& ctx, /// @returns the unwrapped, user-declared constructed type of ty. const ast::NamedType* ConstructedTypeOf(const sem::Type* ty) { while (true) { - if (auto* ptr = ty->As()) { - ty = ptr->StoreType(); + if (auto* ref = ty->As()) { + ty = ref->StoreType(); continue; } if (auto* str = ty->As()) { @@ -466,14 +467,14 @@ struct DecomposeStorageAccess::State { for (auto* member : str->Members()) { auto* offset = ctx.dst->Add("offset", member->Offset()); Symbol load = LoadFunc(ctx, insert_after, buf_ty, - member->Type()->UnwrapAll(), var_user); + member->Type()->UnwrapRef(), var_user); values.emplace_back(ctx.dst->Call(load, "buffer", offset)); } } else if (auto* arr = el_ty->As()) { for (uint32_t i = 0; i < arr->Count(); i++) { auto* offset = ctx.dst->Add("offset", arr->Stride() * i); Symbol load = LoadFunc(ctx, insert_after, buf_ty, - arr->ElemType()->UnwrapAll(), var_user); + arr->ElemType()->UnwrapRef(), var_user); values.emplace_back(ctx.dst->Call(load, "buffer", offset)); } } @@ -546,7 +547,7 @@ struct DecomposeStorageAccess::State { auto* access = ctx.dst->MemberAccessor( "value", ctx.Clone(member->Declaration()->symbol())); Symbol store = StoreFunc(ctx, insert_after, buf_ty, - member->Type()->UnwrapAll(), var_user); + member->Type()->UnwrapRef(), var_user); auto* call = ctx.dst->Call(store, "buffer", offset, access); body.emplace_back(ctx.dst->create(call)); } @@ -555,7 +556,7 @@ struct DecomposeStorageAccess::State { auto* offset = ctx.dst->Add("offset", arr->Stride() * i); auto* access = ctx.dst->IndexAccessor("value", ctx.dst->Expr(i)); Symbol store = StoreFunc(ctx, insert_after, buf_ty, - arr->ElemType()->UnwrapAll(), var_user); + arr->ElemType()->UnwrapRef(), var_user); auto* call = ctx.dst->Call(store, "buffer", offset, access); body.emplace_back(ctx.dst->create(call)); } @@ -661,7 +662,7 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) { state.AddAccess(ident, { var, ToOffset(0u), - var->Type()->UnwrapAll(), + var->Type()->UnwrapRef(), }); } } @@ -681,7 +682,7 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) { accessor, { access.var, Add(std::move(access.offset), std::move(offset)), - vec_ty->type()->UnwrapAll(), + vec_ty->type()->UnwrapRef(), }); } } @@ -694,7 +695,7 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) { { access.var, Add(std::move(access.offset), std::move(offset)), - member->Type()->UnwrapAll(), + member->Type()->UnwrapRef(), }); } } @@ -710,7 +711,7 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) { { access.var, Add(std::move(access.offset), std::move(offset)), - arr->ElemType()->UnwrapAll(), + arr->ElemType()->UnwrapRef(), }); continue; } @@ -720,7 +721,7 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) { { access.var, Add(std::move(access.offset), std::move(offset)), - vec_ty->type()->UnwrapAll(), + vec_ty->type()->UnwrapRef(), }); continue; } @@ -770,8 +771,8 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) { auto* buf = access.var->Declaration(); auto* offset = access.offset->Build(ctx); - auto* buf_ty = access.var->Type()->UnwrapPtr(); - auto* el_ty = access.type->UnwrapAll(); + auto* buf_ty = access.var->Type()->UnwrapRef(); + auto* el_ty = access.type->UnwrapRef(); auto* insert_after = ConstructedTypeOf(access.var->Type()); Symbol func = state.LoadFunc(ctx, insert_after, buf_ty, el_ty, access.var->As()); @@ -785,8 +786,8 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) { for (auto& store : state.stores) { auto* buf = store.target.var->Declaration(); auto* offset = store.target.offset->Build(ctx); - auto* buf_ty = store.target.var->Type()->UnwrapPtr(); - auto* el_ty = store.target.type->UnwrapAll(); + auto* buf_ty = store.target.var->Type()->UnwrapRef(); + auto* el_ty = store.target.type->UnwrapRef(); auto* value = store.assignment->rhs(); auto* insert_after = ConstructedTypeOf(store.target.var->Type()); Symbol func = state.StoreFunc(ctx, insert_after, buf_ty, el_ty, diff --git a/src/transform/external_texture_transform.cc b/src/transform/external_texture_transform.cc index d4095f5044..c8fb07fe1e 100644 --- a/src/transform/external_texture_transform.cc +++ b/src/transform/external_texture_transform.cc @@ -52,7 +52,10 @@ Output ExternalTextureTransform::Run(const Program* in, const DataMap&) { // if the first parameter is an external texture. if (auto* var = sem.Get(call_expr->params()[0])->As()) { - if (var->Variable()->Type()->Is()) { + if (var->Variable() + ->Type() + ->UnwrapRef() + ->Is()) { if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad && call_expr->params().size() != 2) { TINT_ICE(ctx.dst->Diagnostics()) diff --git a/src/transform/transform.cc b/src/transform/transform.cc index d7ead87424..f2884518f8 100644 --- a/src/transform/transform.cc +++ b/src/transform/transform.cc @@ -17,6 +17,7 @@ #include #include "src/program_builder.h" +#include "src/sem/reference_type.h" TINT_INSTANTIATE_TYPEINFO(tint::transform::Data); @@ -107,6 +108,9 @@ ast::Type* Transform::CreateASTTypeFor(CloneContext* ctx, const sem::Type* ty) { return ctx->dst->create( ctx->Clone(s->Declaration()->name())); } + if (auto* s = ty->As()) { + return CreateASTTypeFor(ctx, s->StoreType()); + } TINT_UNREACHABLE(ctx->dst->Diagnostics()) << "Unhandled type: " << ty->TypeInfo().name; return nullptr; diff --git a/src/writer/append_vector.cc b/src/writer/append_vector.cc index 9e64ac40c2..dcf179f46a 100644 --- a/src/writer/append_vector.cc +++ b/src/writer/append_vector.cc @@ -41,7 +41,7 @@ ast::TypeConstructorExpression* AppendVector(ProgramBuilder* b, uint32_t packed_size; const sem::Type* packed_el_sem_ty; auto* vector_sem = b->Sem().Get(vector); - auto* vector_ty = vector_sem->Type()->UnwrapPtr(); + auto* vector_ty = vector_sem->Type()->UnwrapRef(); if (auto* vec = vector_ty->As()) { packed_size = vec->size() + 1; packed_el_sem_ty = vec->type(); @@ -72,7 +72,7 @@ ast::TypeConstructorExpression* AppendVector(ProgramBuilder* b, } else { packed.emplace_back(vector); } - if (packed_el_sem_ty != b->TypeOf(scalar)->UnwrapPtr()) { + if (packed_el_sem_ty != b->TypeOf(scalar)->UnwrapRef()) { // Cast scalar to the vector element type auto* scalar_cast = b->Construct(packed_el_ty, scalar); b->Sem().Add(scalar_cast, b->create( diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc index 95a77f23c5..e894106798 100644 --- a/src/writer/hlsl/generator_impl.cc +++ b/src/writer/hlsl/generator_impl.cc @@ -317,8 +317,8 @@ bool GeneratorImpl::EmitBinary(std::ostream& pre, return true; } - auto* lhs_type = TypeOf(expr->lhs())->UnwrapAll(); - auto* rhs_type = TypeOf(expr->rhs())->UnwrapAll(); + auto* lhs_type = TypeOf(expr->lhs())->UnwrapRef(); + auto* rhs_type = TypeOf(expr->rhs())->UnwrapRef(); // Multiplying by a matrix requires the use of `mul` in order to get the // type of multiply we desire. if (expr->op() == ast::BinaryOp::kMultiply && @@ -854,7 +854,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre, return false; } - auto* texture_type = TypeOf(texture)->UnwrapAll()->As(); + auto* texture_type = TypeOf(texture)->UnwrapRef()->As(); switch (intrinsic->Type()) { case sem::IntrinsicType::kTextureDimensions: @@ -1300,7 +1300,7 @@ bool GeneratorImpl::EmitScalarConstructor( bool GeneratorImpl::EmitTypeConstructor(std::ostream& pre, std::ostream& out, ast::TypeConstructorExpression* expr) { - auto* type = TypeOf(expr); + auto* type = TypeOf(expr)->UnwrapRef(); // If the type constructor is empty then we need to construct with the zero // value for all components. @@ -1699,7 +1699,7 @@ bool GeneratorImpl::EmitEntryPointData( continue; // Global already emitted } - auto* type = var->Type()->UnwrapAccess(); + auto* type = var->Type()->UnwrapRef(); if (auto* strct = type->As()) { out << "ConstantBuffer<" << builder_.Symbols().NameFor(strct->Declaration()->name()) << "> " @@ -1748,8 +1748,9 @@ bool GeneratorImpl::EmitEntryPointData( return false; } - if (!EmitType(out, var->Type(), ast::StorageClass::kStorage, - var->AccessControl(), "")) { + auto* type = var->Type()->UnwrapRef(); + if (!EmitType(out, type, ast::StorageClass::kStorage, var->AccessControl(), + "")) { return false; } @@ -1781,7 +1782,7 @@ bool GeneratorImpl::EmitEntryPointData( auto* var = data.first; auto* deco = data.second; auto* sem = builder_.Sem().Get(var); - auto* type = sem->Type(); + auto* type = sem->Type()->UnwrapRef(); make_indent(out); if (!EmitType(out, type, sem->StorageClass(), sem->AccessControl(), @@ -1832,7 +1833,7 @@ bool GeneratorImpl::EmitEntryPointData( auto* var = data.first; auto* deco = data.second; auto* sem = builder_.Sem().Get(var); - auto* type = sem->Type(); + auto* type = sem->Type()->UnwrapRef(); make_indent(out); if (!EmitType(out, type, sem->StorageClass(), sem->AccessControl(), @@ -1877,7 +1878,7 @@ bool GeneratorImpl::EmitEntryPointData( for (auto* var : func_sem->ReferencedModuleVariables()) { auto* decl = var->Declaration(); - auto* unwrapped_type = var->Type()->UnwrapAll(); + auto* unwrapped_type = var->Type()->UnwrapRef(); if (!emitted_globals.emplace(decl->symbol()).second) { continue; // Global already emitted } @@ -1903,11 +1904,12 @@ bool GeneratorImpl::EmitEntryPointData( } auto name = builder_.Symbols().NameFor(decl->symbol()); - if (!EmitType(out, var->Type(), var->StorageClass(), var->AccessControl(), + auto* type = var->Type()->UnwrapRef(); + if (!EmitType(out, type, var->StorageClass(), var->AccessControl(), name)) { return false; } - if (!var->Type()->Is()) { + if (!type->Is()) { out << " " << name; } @@ -2230,7 +2232,8 @@ bool GeneratorImpl::EmitLoop(std::ostream& out, ast::LoopStatement* stmt) { if (var->constructor() != nullptr) { out << constructor_out.str(); } else { - if (!EmitZeroValue(out, builder_.Sem().Get(var)->Type())) { + auto* type = builder_.Sem().Get(var)->Type()->UnwrapRef(); + if (!EmitZeroValue(out, type)) { return false; } } @@ -2639,7 +2642,7 @@ bool GeneratorImpl::EmitVariable(std::ostream& out, make_indent(out); auto* sem = builder_.Sem().Get(var); - auto* type = sem->Type(); + auto* type = sem->Type()->UnwrapRef(); // TODO(dsinclair): Handle variable decorations if (!var->decorations().empty()) { diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc index 08255ae362..c4d25cf43e 100644 --- a/src/writer/msl/generator_impl.cc +++ b/src/writer/msl/generator_impl.cc @@ -41,6 +41,7 @@ #include "src/sem/member_accessor_expression.h" #include "src/sem/multisampled_texture_type.h" #include "src/sem/pointer_type.h" +#include "src/sem/reference_type.h" #include "src/sem/sampled_texture_type.h" #include "src/sem/storage_texture_type.h" #include "src/sem/struct.h" @@ -177,7 +178,7 @@ bool GeneratorImpl::EmitArrayAccessor(ast::ArrayAccessorExpression* expr) { bool GeneratorImpl::EmitBitcast(ast::BitcastExpression* expr) { out_ << "as_type<"; - if (!EmitType(TypeOf(expr), "")) { + if (!EmitType(TypeOf(expr)->UnwrapRef(), "")) { return false; } @@ -484,7 +485,7 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr, return false; } - auto* texture_type = TypeOf(texture)->UnwrapAll()->As(); + auto* texture_type = TypeOf(texture)->UnwrapRef()->As(); switch (intrinsic->Type()) { case sem::IntrinsicType::kTextureDimensions: { @@ -530,7 +531,7 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr, get_dim(dims[0]); out_ << ")"; } else { - EmitType(TypeOf(expr), ""); + EmitType(TypeOf(expr)->UnwrapRef(), ""); out_ << "("; for (size_t i = 0; i < dims.size(); i++) { if (i > 0) { @@ -880,7 +881,7 @@ bool GeneratorImpl::EmitContinue(ast::ContinueStatement*) { } bool GeneratorImpl::EmitTypeConstructor(ast::TypeConstructorExpression* expr) { - auto* type = TypeOf(expr); + auto* type = TypeOf(expr)->UnwrapRef(); if (type->IsAnyOf()) { out_ << "{"; @@ -1016,7 +1017,7 @@ bool GeneratorImpl::EmitEntryPointData(ast::Function* func) { uint32_t loc = data.second; make_indent(); - if (!EmitType(program_->Sem().Get(var)->Type(), + if (!EmitType(program_->Sem().Get(var)->Type()->UnwrapRef(), program_->Symbols().NameFor(var->symbol()))) { return false; } @@ -1053,7 +1054,7 @@ bool GeneratorImpl::EmitEntryPointData(ast::Function* func) { auto* deco = data.second; make_indent(); - if (!EmitType(program_->Sem().Get(var)->Type(), + if (!EmitType(program_->Sem().Get(var)->Type()->UnwrapRef(), program_->Symbols().NameFor(var->symbol()))) { return false; } @@ -1267,7 +1268,7 @@ bool GeneratorImpl::EmitFunctionInternal(ast::Function* func, first = false; out_ << "thread "; - if (!EmitType(var->Type(), "")) { + if (!EmitType(var->Type()->UnwrapRef(), "")) { return false; } out_ << "& " << program_->Symbols().NameFor(var->Declaration()->symbol()); @@ -1282,7 +1283,7 @@ bool GeneratorImpl::EmitFunctionInternal(ast::Function* func, out_ << "constant "; // TODO(dsinclair): Can arrays be uniform? If so, fix this ... - if (!EmitType(var->Type(), "")) { + if (!EmitType(var->Type()->UnwrapRef(), "")) { return false; } out_ << "& " << program_->Symbols().NameFor(var->Declaration()->symbol()); @@ -1300,7 +1301,7 @@ bool GeneratorImpl::EmitFunctionInternal(ast::Function* func, } out_ << "device "; - if (!EmitType(var->Type(), "")) { + if (!EmitType(var->Type()->UnwrapRef(), "")) { return false; } out_ << "& " << program_->Symbols().NameFor(var->Declaration()->symbol()); @@ -1414,7 +1415,7 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) { } first = false; - auto* type = program_->Sem().Get(var)->Type(); + auto* type = program_->Sem().Get(var)->Type()->UnwrapRef(); if (!EmitType(type, "")) { return false; @@ -1462,7 +1463,7 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) { auto* builtin = data.second; - if (!EmitType(var->Type(), "")) { + if (!EmitType(var->Type()->UnwrapRef(), "")) { return false; } @@ -1497,7 +1498,7 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) { out_ << "constant "; // TODO(dsinclair): Can you have a uniform array? If so, this needs to be // updated to handle arrays property. - if (!EmitType(var->Type(), "")) { + if (!EmitType(var->Type()->UnwrapRef(), "")) { return false; } out_ << "& " << program_->Symbols().NameFor(var->Declaration()->symbol()) @@ -1522,7 +1523,7 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) { } out_ << "device "; - if (!EmitType(var->Type(), "")) { + if (!EmitType(var->Type()->UnwrapRef(), "")) { return false; } out_ << "& " << program_->Symbols().NameFor(var->Declaration()->symbol()) @@ -1659,7 +1660,8 @@ bool GeneratorImpl::EmitLoop(ast::LoopStatement* stmt) { return false; } } else { - if (!EmitZeroValue(program_->Sem().Get(var)->Type())) { + auto* type = program_->Sem().Get(var)->Type()->UnwrapRef(); + if (!EmitZeroValue(type)) { return false; } } @@ -2186,13 +2188,14 @@ bool GeneratorImpl::EmitVariable(const sem::Variable* var, diagnostics_.add_error("Variable decorations are not handled yet"); return false; } - if (decl->is_const()) { - out_ << "const "; - } - if (!EmitType(var->Type(), program_->Symbols().NameFor(decl->symbol()))) { + auto* type = var->Type()->UnwrapRef(); + if (!EmitType(type, program_->Symbols().NameFor(decl->symbol()))) { return false; } - if (!var->Type()->Is()) { + if (decl->is_const()) { + out_ << " const"; + } + if (!type->Is()) { out_ << " " << program_->Symbols().NameFor(decl->symbol()); } @@ -2206,7 +2209,7 @@ bool GeneratorImpl::EmitVariable(const sem::Variable* var, var->StorageClass() == ast::StorageClass::kFunction || var->StorageClass() == ast::StorageClass::kNone || var->StorageClass() == ast::StorageClass::kOutput) { - if (!EmitZeroValue(var->Type())) { + if (!EmitZeroValue(type)) { return false; } } @@ -2231,7 +2234,7 @@ bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) { } out_ << "constant "; - auto* type = program_->Sem().Get(var)->Type(); + auto* type = program_->Sem().Get(var)->Type()->UnwrapRef(); if (!EmitType(type, program_->Symbols().NameFor(var->symbol()))) { return false; } @@ -2265,7 +2268,7 @@ GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign( // https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf // 2.2.3 Packed Vector Types auto num_els = vec->size(); - auto* el_ty = vec->type()->UnwrapAll(); + auto* el_ty = vec->type(); if (el_ty->IsAnyOf()) { return SizeAndAlign{num_els * 4, 4}; } @@ -2276,7 +2279,7 @@ GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign( // 2.3 Matrix Data Types auto cols = mat->columns(); auto rows = mat->rows(); - auto* el_ty = mat->type()->UnwrapAll(); + auto* el_ty = mat->type(); if (el_ty->IsAnyOf()) { static constexpr SizeAndAlign table[] = { /* float2x2 */ {16, 8}, diff --git a/src/writer/msl/generator_impl_function_test.cc b/src/writer/msl/generator_impl_function_test.cc index dafc9ca2ee..83ffab058d 100644 --- a/src/writer/msl/generator_impl_function_test.cc +++ b/src/writer/msl/generator_impl_function_test.cc @@ -112,7 +112,7 @@ struct tint_symbol_2 { }; fragment tint_symbol_2 frag_main(tint_symbol_1 tint_symbol [[stage_in]]) { - const float foo = tint_symbol.foo; + float const foo = tint_symbol.foo; return {foo}; } @@ -146,7 +146,7 @@ struct tint_symbol_2 { }; fragment tint_symbol_2 frag_main(tint_symbol_1 tint_symbol [[stage_in]]) { - const float4 coord = tint_symbol.coord; + float4 const coord = tint_symbol.coord; return {coord.x}; } @@ -214,14 +214,14 @@ struct tint_symbol_3 { }; vertex tint_symbol vert_main() { - const Interface tint_symbol_1 = {0.5f, 0.25f, float4(0.0f)}; + Interface const tint_symbol_1 = {0.5f, 0.25f, float4(0.0f)}; return {tint_symbol_1.col1, tint_symbol_1.col2, tint_symbol_1.pos}; } fragment void frag_main(tint_symbol_3 tint_symbol_2 [[stage_in]]) { - const Interface colors = {tint_symbol_2.col1, tint_symbol_2.col2, tint_symbol_2.pos}; - const float r = colors.col1; - const float g = colors.col2; + Interface const colors = {tint_symbol_2.col1, tint_symbol_2.col2, tint_symbol_2.pos}; + float const r = colors.col1; + float const g = colors.col2; return; } @@ -283,12 +283,12 @@ VertexOutput foo(float x) { } vertex tint_symbol vert_main1() { - const VertexOutput tint_symbol_1 = {foo(0.5f)}; + VertexOutput const tint_symbol_1 = {foo(0.5f)}; return {tint_symbol_1.pos}; } vertex tint_symbol_2 vert_main2() { - const VertexOutput tint_symbol_3 = {foo(0.25f)}; + VertexOutput const tint_symbol_3 = {foo(0.25f)}; return {tint_symbol_3.pos}; } diff --git a/src/writer/msl/generator_impl_intrinsic_texture_test.cc b/src/writer/msl/generator_impl_intrinsic_texture_test.cc index 02d058db39..901f100f8f 100644 --- a/src/writer/msl/generator_impl_intrinsic_texture_test.cc +++ b/src/writer/msl/generator_impl_intrinsic_texture_test.cc @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "src/ast/call_statement.h" #include "src/ast/intrinsic_texture_helper_test.h" #include "src/writer/msl/test_helper.h" @@ -259,7 +260,14 @@ TEST_P(MslGeneratorIntrinsicTextureTest, Call) { auto* call = create(Expr(param.function), param.args(this)); - WrapInFunction(call); + + Func("main", ast::VariableList{}, ty.void_(), + ast::StatementList{ + create(call), + }, + ast::DecorationList{ + Stage(ast::PipelineStage::kFragment), + }); GeneratorImpl& gen = Build(); diff --git a/src/writer/msl/generator_impl_variable_decl_statement_test.cc b/src/writer/msl/generator_impl_variable_decl_statement_test.cc index 04e7e345c9..548a705958 100644 --- a/src/writer/msl/generator_impl_variable_decl_statement_test.cc +++ b/src/writer/msl/generator_impl_variable_decl_statement_test.cc @@ -48,7 +48,7 @@ TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Const) { gen.increment_indent(); ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error(); - EXPECT_EQ(gen.result(), " const float a = float(0.0f);\n"); + EXPECT_EQ(gen.result(), " float const a = float(0.0f);\n"); } TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Array) { diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc index 9c2cf363fb..22f4a6a71a 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc @@ -28,9 +28,11 @@ #include "src/sem/intrinsic.h" #include "src/sem/member_accessor_expression.h" #include "src/sem/multisampled_texture_type.h" +#include "src/sem/reference_type.h" #include "src/sem/sampled_texture_type.h" #include "src/sem/struct.h" #include "src/sem/variable.h" +#include "src/utils/get_or_create.h" #include "src/writer/append_vector.h" namespace tint { @@ -357,7 +359,7 @@ bool Builder::GenerateAssignStatement(ast::AssignmentStatement* assign) { return false; } - // If the thing we're assigning is a pointer then we must load it first. + // If the thing we're assigning is a reference then we must load it first. auto* type = TypeOf(assign->rhs()); rhs_id = GenerateLoadIfNeeded(type, rhs_id); @@ -598,7 +600,9 @@ bool Builder::GenerateFunctionVariable(ast::Variable* var) { return false; } auto* type = TypeOf(var->constructor()); - init_id = GenerateLoadIfNeeded(type, init_id); + if (type->Is()) { + init_id = GenerateLoadIfNeeded(type, init_id); + } } if (var->is_const()) { @@ -615,8 +619,7 @@ bool Builder::GenerateFunctionVariable(ast::Variable* var) { auto var_id = result.to_i(); auto sc = ast::StorageClass::kFunction; auto* type = builder_.Sem().Get(var)->Type(); - sem::Pointer pt(type, sc); - auto type_id = GenerateTypeIfNeeded(&pt); + auto type_id = GenerateTypeIfNeeded(type); if (type_id == 0) { return false; } @@ -627,7 +630,7 @@ bool Builder::GenerateFunctionVariable(ast::Variable* var) { // TODO(dsinclair) We could detect if the constructor is fully const and emit // an initializer value for the variable instead of doing the OpLoad. - auto null_id = GenerateConstantNullIfNeeded(type->UnwrapPtr()); + auto null_id = GenerateConstantNullIfNeeded(type->UnwrapRef()); if (null_id == 0) { return 0; } @@ -654,6 +657,7 @@ bool Builder::GenerateStore(uint32_t to, uint32_t from) { bool Builder::GenerateGlobalVariable(ast::Variable* var) { auto* sem = builder_.Sem().Get(var); + auto* type = sem->Type()->UnwrapRef(); uint32_t init_id = 0; if (var->has_constructor()) { @@ -679,16 +683,16 @@ bool Builder::GenerateGlobalVariable(ast::Variable* var) { } // SPIR-V requires specialization constants to have initializers. - if (sem->Type()->Is()) { + if (type->Is()) { ast::FloatLiteral l(ProgramID(), Source{}, 0.0f); init_id = GenerateLiteralIfNeeded(var, &l); - } else if (sem->Type()->Is()) { + } else if (type->Is()) { ast::UintLiteral l(ProgramID(), Source{}, 0); init_id = GenerateLiteralIfNeeded(var, &l); - } else if (sem->Type()->Is()) { + } else if (type->Is()) { ast::SintLiteral l(ProgramID(), Source{}, 0); init_id = GenerateLiteralIfNeeded(var, &l); - } else if (sem->Type()->Is()) { + } else if (type->Is()) { ast::BoolLiteral l(ProgramID(), Source{}, false); init_id = GenerateLiteralIfNeeded(var, &l); } else { @@ -715,8 +719,7 @@ bool Builder::GenerateGlobalVariable(ast::Variable* var) { ? ast::StorageClass::kPrivate : sem->StorageClass(); - sem::Pointer pt(sem->Type(), sc); - auto type_id = GenerateTypeIfNeeded(&pt); + auto type_id = GenerateTypeIfNeeded(sem->Type()); if (type_id == 0) { return false; } @@ -728,8 +731,6 @@ bool Builder::GenerateGlobalVariable(ast::Variable* var) { OperandList ops = {Operand::Int(type_id), result, Operand::Int(ConvertStorageClass(sc))}; - auto* type = sem->Type(); - if (var->has_constructor()) { ops.push_back(Operand::Int(init_id)); } else if (sem->AccessControl() != ast::AccessControl::kInvalid) { @@ -806,8 +807,10 @@ bool Builder::GenerateArrayAccessor(ast::ArrayAccessorExpression* expr, auto* type = TypeOf(expr->idx_expr()); idx_id = GenerateLoadIfNeeded(type, idx_id); - // If the source is a pointer, we access chain into it. - if (info->source_type->Is()) { + // If the source is a reference, we access chain into it. + // In the future, pointers may support access-chaining. + // See https://github.com/gpuweb/gpuweb/pull/1580 + if (info->source_type->Is()) { info->access_chain_indices.push_back(idx_id); info->source_type = TypeOf(expr); return true; @@ -870,7 +873,7 @@ bool Builder::GenerateMemberAccessor(ast::MemberAccessorExpression* expr, if (auto* access = expr_sem->As()) { uint32_t idx = access->Member()->Index(); - if (info->source_type->Is()) { + if (info->source_type->Is()) { auto idx_id = GenerateConstantIfNeeded(ScalarConstant::U32(idx)); if (idx_id == 0) { return 0; @@ -903,7 +906,7 @@ bool Builder::GenerateMemberAccessor(ast::MemberAccessorExpression* expr, // Single element swizzle is either an access chain or a composite extract auto& indices = swizzle->Indices(); if (indices.size() == 1) { - if (info->source_type->Is()) { + if (info->source_type->Is()) { auto idx_id = GenerateConstantIfNeeded(ScalarConstant::U32(indices[0])); if (idx_id == 0) { return 0; @@ -954,7 +957,7 @@ bool Builder::GenerateMemberAccessor(ast::MemberAccessorExpression* expr, } info->source_id = GenerateLoadIfNeeded(expr_type, extract_id); - info->source_type = expr_type->UnwrapPtr(); + info->source_type = expr_type->UnwrapRef(); info->access_chain_indices.clear(); } @@ -1022,25 +1025,31 @@ uint32_t Builder::GenerateAccessorExpression(ast::Expression* expr) { // If our initial access is into a non-pointer array, and either has a // non-scalar element type or the accessor uses a non-literal index, then we // need to load that array into a variable in order to access chain into it. - // TODO(jrprice): The non-scalar part shouldn't be necessary, but is tied to - // how the Resolver currently determines the type of these expression. This - // should be fixed when proper support for ptr/ref types is implemented. - if (auto* array = accessors[0]->As()) { - auto* ary_res_type = TypeOf(array->array())->As(); - if (ary_res_type && - (!ary_res_type->ElemType()->is_scalar() || - !array->idx_expr()->Is())) { - // Wrap the source type in a pointer to function storage. - auto ptr = - builder_.ty.pointer(ary_res_type, ast::StorageClass::kFunction); - auto result_type_id = GenerateTypeIfNeeded(ptr); + + // TODO(bclayton): The requirement for scalar element types is because of + // arrays-of-arrays - this logic only considers whether the root index is + // compile-time-constant, and not whether there are any dynamic, inner-array + // indexing being performed. Instead of trying to do complex hoisting in this + // writer, move this hoisting into the transform::Spirv sanitizer. + + bool needs_load = false; // Was the expression hoist to a temporary variable? + if (auto* access = accessors[0]->As()) { + auto* array = TypeOf(access->array())->As(); + bool trivial_indexing = + array && array->ElemType()->is_scalar() && + access->idx_expr()->Is(); + if (array && !trivial_indexing) { + // Wrap the source type in a reference to function storage. + auto* ref = + builder_.create(array, ast::StorageClass::kFunction); + auto result_type_id = GenerateTypeIfNeeded(ref); if (result_type_id == 0) { return 0; } auto ary_result = result_op(); - auto init = GenerateConstantNullIfNeeded(ary_res_type); + auto init = GenerateConstantNullIfNeeded(array); // If we're access chaining into an array then we must be in a function push_function_var( @@ -1054,7 +1063,8 @@ uint32_t Builder::GenerateAccessorExpression(ast::Expression* expr) { } info.source_id = ary_result.to_i(); - info.source_type = ptr; + info.source_type = ref; + needs_load = true; } } @@ -1076,17 +1086,12 @@ uint32_t Builder::GenerateAccessorExpression(ast::Expression* expr) { } if (!info.access_chain_indices.empty()) { - bool needs_load = false; - auto* ptr = TypeOf(expr); - if (!ptr->Is()) { - // We are performing an access chain but the final result is not a - // pointer, so we need to perform a load to get it. This happens when we - // have to copy the source expression into a function variable. - ptr = builder_.ty.pointer(ptr, ast::StorageClass::kFunction); - needs_load = true; + auto* type = TypeOf(expr); + if (needs_load) { + type = + builder_.create(type, ast::StorageClass::kFunction); } - - auto result_type_id = GenerateTypeIfNeeded(ptr); + auto result_type_id = GenerateTypeIfNeeded(type); if (result_type_id == 0) { return 0; } @@ -1107,7 +1112,7 @@ uint32_t Builder::GenerateAccessorExpression(ast::Expression* expr) { // Load from the access chain result if required. if (needs_load) { - info.source_id = GenerateLoadIfNeeded(ptr, result_id); + info.source_id = GenerateLoadIfNeeded(type, result_id); } } @@ -1127,16 +1132,18 @@ uint32_t Builder::GenerateIdentifierExpression( } uint32_t Builder::GenerateLoadIfNeeded(const sem::Type* type, uint32_t id) { - if (!type->Is()) { + if (auto* ref = type->As()) { + type = ref->StoreType(); + } else { return id; } - auto type_id = GenerateTypeIfNeeded(type->UnwrapPtr()); + auto type_id = GenerateTypeIfNeeded(type); auto result = result_op(); auto result_id = result.to_i(); if (!push_function_inst(spv::Op::OpLoad, {Operand::Int(type_id), result, Operand::Int(id)})) { - return false; + return 0; } return result_id; } @@ -1149,6 +1156,27 @@ uint32_t Builder::GenerateUnaryOpExpression(ast::UnaryOpExpression* expr) { if (val_id == 0) { return 0; } + + spv::Op op = spv::Op::OpNop; + switch (expr->op()) { + case ast::UnaryOp::kNegation: + if (TypeOf(expr)->is_float_scalar_or_vector()) { + op = spv::Op::OpFNegate; + } else { + op = spv::Op::OpSNegate; + } + break; + case ast::UnaryOp::kNot: + op = spv::Op::OpLogicalNot; + break; + case ast::UnaryOp::kAddressOf: + case ast::UnaryOp::kIndirection: + // Address-of converts a reference to a pointer, and dereference converts + // a pointer to a reference. These are the same thing in SPIR-V, so this + // is a no-op. + return val_id; + } + val_id = GenerateLoadIfNeeded(TypeOf(expr->expr()), val_id); auto type_id = GenerateTypeIfNeeded(TypeOf(expr)); @@ -1156,21 +1184,6 @@ uint32_t Builder::GenerateUnaryOpExpression(ast::UnaryOpExpression* expr) { return 0; } - spv::Op op = spv::Op::OpNop; - if (expr->op() == ast::UnaryOp::kNegation) { - if (TypeOf(expr)->is_float_scalar_or_vector()) { - op = spv::Op::OpFNegate; - } else { - op = spv::Op::OpSNegate; - } - } else if (expr->op() == ast::UnaryOp::kNot) { - op = spv::Op::OpLogicalNot; - } - if (op == spv::Op::OpNop) { - error_ = "invalid unary op type"; - return 0; - } - if (!push_function_inst( op, {Operand::Int(type_id), result, Operand::Int(val_id)})) { return false; @@ -1218,7 +1231,7 @@ bool Builder::is_constructor_const(ast::Expression* expr, bool is_global_init) { } auto* tc = constructor->As(); - auto* result_type = TypeOf(tc)->UnwrapAll(); + auto* result_type = TypeOf(tc)->UnwrapRef(); for (size_t i = 0; i < tc->values().size(); ++i) { auto* e = tc->values()[i]; @@ -1246,17 +1259,17 @@ bool Builder::is_constructor_const(ast::Expression* expr, bool is_global_init) { continue; } - const sem::Type* subtype = result_type->UnwrapAll(); + const sem::Type* subtype = result_type->UnwrapRef(); if (auto* vec = subtype->As()) { - subtype = vec->type()->UnwrapAll(); + subtype = vec->type(); } else if (auto* mat = subtype->As()) { - subtype = mat->type()->UnwrapAll(); + subtype = mat->type(); } else if (auto* arr = subtype->As()) { - subtype = arr->ElemType()->UnwrapAll(); + subtype = arr->ElemType(); } else if (auto* str = subtype->As()) { - subtype = str->Members()[i]->Type()->UnwrapAll(); + subtype = str->Members()[i]->Type(); } - if (subtype != TypeOf(sc)->UnwrapAll()) { + if (subtype != TypeOf(sc)->UnwrapRef()) { return false; } } @@ -1272,13 +1285,13 @@ uint32_t Builder::GenerateTypeConstructorExpression( // Generate the zero initializer if there are no values provided. if (values.empty()) { - return GenerateConstantNullIfNeeded(result_type->UnwrapPtr()); + return GenerateConstantNullIfNeeded(result_type->UnwrapRef()); } std::ostringstream out; out << "__const_" << init->type()->FriendlyName(builder_.Symbols()) << "_"; - result_type = result_type->UnwrapAll(); + result_type = result_type->UnwrapRef(); bool constructor_is_const = is_constructor_const(init, is_global_init); if (has_error()) { return 0; @@ -1288,7 +1301,7 @@ uint32_t Builder::GenerateTypeConstructorExpression( if (auto* res_vec = result_type->As()) { if (res_vec->type()->is_scalar()) { - auto* value_type = TypeOf(values[0])->UnwrapAll(); + auto* value_type = TypeOf(values[0])->UnwrapRef(); if (auto* val_vec = value_type->As()) { if (val_vec->type()->is_scalar()) { can_cast_or_copy = res_vec->size() == val_vec->size(); @@ -1327,7 +1340,7 @@ uint32_t Builder::GenerateTypeConstructorExpression( return 0; } - auto* value_type = TypeOf(e)->UnwrapPtr(); + auto* value_type = TypeOf(e)->UnwrapRef(); // If the result and value types are the same we can just use the object. // If the result is not a vector then we should have validated that the // value type is a correctly sized vector so we can just use it directly. @@ -1444,7 +1457,7 @@ uint32_t Builder::GenerateCastOrCopyOrPassthrough(const sem::Type* to_type, } val_id = GenerateLoadIfNeeded(TypeOf(from_expr), val_id); - auto* from_type = TypeOf(from_expr)->UnwrapPtr(); + auto* from_type = TypeOf(from_expr)->UnwrapRef(); spv::Op op = spv::Op::OpNop; if ((from_type->Is() && to_type->Is()) || @@ -1728,8 +1741,8 @@ uint32_t Builder::GenerateBinaryExpression(ast::BinaryExpression* expr) { // Handle int and float and the vectors of those types. Other types // should have been rejected by validation. - auto* lhs_type = TypeOf(expr->lhs())->UnwrapAll(); - auto* rhs_type = TypeOf(expr->rhs())->UnwrapAll(); + auto* lhs_type = TypeOf(expr->lhs())->UnwrapRef(); + auto* rhs_type = TypeOf(expr->rhs())->UnwrapRef(); bool lhs_is_float_or_vec = lhs_type->is_float_scalar_or_vector(); bool lhs_is_unsigned = lhs_type->is_unsigned_scalar_or_vector(); @@ -1904,13 +1917,18 @@ uint32_t Builder::GenerateCallExpression(ast::CallExpression* expr) { } ops.push_back(Operand::Int(func_id)); - for (auto* param : expr->params()) { - auto id = GenerateExpression(param); + size_t arg_idx = 0; + for (auto* arg : expr->params()) { + auto id = GenerateExpression(arg); + if (id == 0) { + return 0; + } + id = GenerateLoadIfNeeded(TypeOf(arg), id); if (id == 0) { return 0; } - id = GenerateLoadIfNeeded(TypeOf(param), id); ops.push_back(Operand::Int(id)); + arg_idx++; } if (!push_function_inst(spv::Op::OpFunctionCall, std::move(ops))) { @@ -1982,7 +2000,7 @@ uint32_t Builder::GenerateIntrinsic(ast::CallExpression* call, } params.push_back(Operand::Int(struct_id)); - auto* type = TypeOf(accessor->structure())->UnwrapAll(); + auto* type = TypeOf(accessor->structure())->UnwrapRef(); if (!type->Is()) { error_ = "invalid type (" + type->type_name() + ") for runtime array length"; @@ -2134,7 +2152,7 @@ bool Builder::GenerateTextureIntrinsic(ast::CallExpression* call, TINT_ICE(builder_.Diagnostics()) << "missing texture argument"; } - auto* texture_type = TypeOf(texture)->UnwrapAll()->As(); + auto* texture_type = TypeOf(texture)->UnwrapRef()->As(); auto op = spv::Op::OpNop; @@ -2580,8 +2598,8 @@ uint32_t Builder::GenerateBitcastExpression(ast::BitcastExpression* expr) { val_id = GenerateLoadIfNeeded(TypeOf(expr->expr()), val_id); // Bitcast does not allow same types, just emit a CopyObject - auto* to_type = TypeOf(expr)->UnwrapPtr(); - auto* from_type = TypeOf(expr->expr())->UnwrapPtr(); + auto* to_type = TypeOf(expr)->UnwrapRef(); + auto* from_type = TypeOf(expr->expr())->UnwrapRef(); if (to_type->type_name() == from_type->type_name()) { if (!push_function_inst( spv::Op::OpCopyObject, @@ -2932,84 +2950,97 @@ uint32_t Builder::GenerateTypeIfNeeded(const sem::Type* type) { return 0; } - auto val = type_name_to_id_.find(type->type_name()); - if (val != type_name_to_id_.end()) { - return val->second; - } - - auto result = result_op(); - auto id = result.to_i(); - if (auto* arr = type->As()) { - if (!GenerateArrayType(arr, result)) { - return 0; - } - } else if (type->Is()) { - push_type(spv::Op::OpTypeBool, {result}); - } else if (type->Is()) { - push_type(spv::Op::OpTypeFloat, {result, Operand::Int(32)}); - } else if (type->Is()) { - push_type(spv::Op::OpTypeInt, {result, Operand::Int(32), Operand::Int(1)}); - } else if (auto* mat = type->As()) { - if (!GenerateMatrixType(mat, result)) { - return 0; - } - } else if (auto* ptr = type->As()) { - if (!GeneratePointerType(ptr, result)) { - return 0; - } - } else if (auto* str = type->As()) { - if (!GenerateStructType(str, result)) { - return 0; - } - } else if (type->Is()) { - push_type(spv::Op::OpTypeInt, {result, Operand::Int(32), Operand::Int(0)}); - } else if (auto* vec = type->As()) { - if (!GenerateVectorType(vec, result)) { - return 0; - } - } else if (type->Is()) { - push_type(spv::Op::OpTypeVoid, {result}); - } else if (auto* tex = type->As()) { - if (!GenerateTextureType(tex, result)) { - return 0; - } - - if (auto* st = tex->As()) { - // Register all three access types of StorageTexture names. In SPIR-V, we - // must output a single type, while the variable is annotated with the - // access type. Doing this ensures we de-dupe. - type_name_to_id_[builder_ - .create( - st->dim(), st->image_format(), - ast::AccessControl::kReadOnly, st->type()) - ->type_name()] = id; - type_name_to_id_[builder_ - .create( - st->dim(), st->image_format(), - ast::AccessControl::kWriteOnly, st->type()) - ->type_name()] = id; - type_name_to_id_[builder_ - .create( - st->dim(), st->image_format(), - ast::AccessControl::kReadWrite, st->type()) - ->type_name()] = id; - } - - } else if (type->Is()) { - push_type(spv::Op::OpTypeSampler, {result}); - - // Register both of the sampler type names. In SPIR-V they're the same - // sampler type, so we need to match that when we do the dedup check. - type_name_to_id_["__sampler_sampler"] = id; - type_name_to_id_["__sampler_comparison"] = id; - + // Pointers and References both map to a SPIR-V pointer type. + // Transform a Reference to a Pointer to prevent these having duplicated + // definitions in the generated SPIR-V. Note that nested references are not + // legal, so only considering the top-level type is fine. + std::string type_name; + if (auto* ref = type->As()) { + type_name = sem::Pointer(ref->StoreType(), ref->StorageClass()).type_name(); } else { - error_ = "unable to convert type: " + type->type_name(); - return 0; + type_name = type->type_name(); } - type_name_to_id_[type->type_name()] = id; - return id; + return utils::GetOrCreate(type_name_to_id_, type_name, [&]() -> uint32_t { + auto result = result_op(); + auto id = result.to_i(); + if (auto* arr = type->As()) { + if (!GenerateArrayType(arr, result)) { + return 0; + } + } else if (type->Is()) { + push_type(spv::Op::OpTypeBool, {result}); + } else if (type->Is()) { + push_type(spv::Op::OpTypeFloat, {result, Operand::Int(32)}); + } else if (type->Is()) { + push_type(spv::Op::OpTypeInt, + {result, Operand::Int(32), Operand::Int(1)}); + } else if (auto* mat = type->As()) { + if (!GenerateMatrixType(mat, result)) { + return 0; + } + } else if (auto* ptr = type->As()) { + if (!GeneratePointerType(ptr, result)) { + return 0; + } + } else if (auto* ref = type->As()) { + if (!GenerateReferenceType(ref, result)) { + return 0; + } + } else if (auto* str = type->As()) { + if (!GenerateStructType(str, result)) { + return 0; + } + } else if (type->Is()) { + push_type(spv::Op::OpTypeInt, + {result, Operand::Int(32), Operand::Int(0)}); + } else if (auto* vec = type->As()) { + if (!GenerateVectorType(vec, result)) { + return 0; + } + } else if (type->Is()) { + push_type(spv::Op::OpTypeVoid, {result}); + } else if (auto* tex = type->As()) { + if (!GenerateTextureType(tex, result)) { + return 0; + } + + if (auto* st = tex->As()) { + // Register all three access types of StorageTexture names. In SPIR-V, + // we must output a single type, while the variable is annotated with + // the access type. Doing this ensures we de-dupe. + type_name_to_id_[builder_ + .create( + st->dim(), st->image_format(), + ast::AccessControl::kReadOnly, st->type()) + ->type_name()] = id; + type_name_to_id_[builder_ + .create( + st->dim(), st->image_format(), + ast::AccessControl::kWriteOnly, st->type()) + ->type_name()] = id; + type_name_to_id_[builder_ + .create( + st->dim(), st->image_format(), + ast::AccessControl::kReadWrite, st->type()) + ->type_name()] = id; + } + + } else if (type->Is()) { + push_type(spv::Op::OpTypeSampler, {result}); + + // Register both of the sampler type names. In SPIR-V they're the same + // sampler type, so we need to match that when we do the dedup check. + type_name_to_id_["__sampler_sampler"] = id; + type_name_to_id_["__sampler_comparison"] = id; + + } else { + error_ = "unable to convert type: " + type->type_name(); + return 0; + } + + return id; + }); } // TODO(tommek): Cover multisampled textures here when they're included in AST @@ -3131,8 +3162,8 @@ bool Builder::GenerateMatrixType(const sem::Matrix* mat, bool Builder::GeneratePointerType(const sem::Pointer* ptr, const Operand& result) { - auto pointee_id = GenerateTypeIfNeeded(ptr->StoreType()); - if (pointee_id == 0) { + auto subtype_id = GenerateTypeIfNeeded(ptr->StoreType()); + if (subtype_id == 0) { return false; } @@ -3143,7 +3174,26 @@ bool Builder::GeneratePointerType(const sem::Pointer* ptr, } push_type(spv::Op::OpTypePointer, - {result, Operand::Int(stg_class), Operand::Int(pointee_id)}); + {result, Operand::Int(stg_class), Operand::Int(subtype_id)}); + + return true; +} + +bool Builder::GenerateReferenceType(const sem::Reference* ref, + const Operand& result) { + auto subtype_id = GenerateTypeIfNeeded(ref->StoreType()); + if (subtype_id == 0) { + return false; + } + + auto stg_class = ConvertStorageClass(ref->StorageClass()); + if (stg_class == SpvStorageClassMax) { + error_ = "invalid storage class for reference"; + return false; + } + + push_type(spv::Op::OpTypePointer, + {result, Operand::Int(stg_class), Operand::Int(subtype_id)}); return true; } diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h index 53c917b8f6..98675ff37c 100644 --- a/src/writer/spirv/builder.h +++ b/src/writer/spirv/builder.h @@ -43,6 +43,7 @@ namespace tint { // Forward declarations namespace sem { class Call; +class Reference; } // namespace sem namespace writer { @@ -66,7 +67,7 @@ class Builder { /// result_type of the current source defined above. const sem::Type* source_type; /// A list of access chain indices to emit. Note, we _only_ have access - /// chain indices if the source is pointer. + /// chain indices if the source is reference. std::vector access_chain_indices; }; @@ -411,7 +412,7 @@ class Builder { /// Geneates an OpLoad /// @param type the type to load /// @param id the variable id to load - /// @returns the ID of the loaded value or `id` if type is not a pointer + /// @returns the ID of the loaded value or `id` if type is not a reference uint32_t GenerateLoadIfNeeded(const sem::Type* type, uint32_t id); /// Generates an OpStore. Emits an error and returns false if we're /// currently outside a function. @@ -443,6 +444,11 @@ class Builder { /// @param result the result operand /// @returns true if the pointer was successfully generated bool GeneratePointerType(const sem::Pointer* ptr, const Operand& result); + /// Generates a reference type declaration + /// @param ref the reference type to generate + /// @param result the result operand + /// @returns true if the reference was successfully generated + bool GenerateReferenceType(const sem::Reference* ref, const Operand& result); /// Generates a vector type declaration /// @param struct_type the vector to generate /// @param result the result operand diff --git a/src/writer/spirv/builder_accessor_expression_test.cc b/src/writer/spirv/builder_accessor_expression_test.cc index 6962231cb6..6e36a069b6 100644 --- a/src/writer/spirv/builder_accessor_expression_test.cc +++ b/src/writer/spirv/builder_accessor_expression_test.cc @@ -766,7 +766,7 @@ TEST_F(BuilderTest, Accessor_Array_Of_Vec) { b.push_function(Function{}); ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error(); - EXPECT_EQ(b.GenerateAccessorExpression(expr), 18u) << b.error(); + EXPECT_EQ(b.GenerateAccessorExpression(expr), 19u) << b.error(); EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 %2 = OpTypeVector %3 2 @@ -791,6 +791,57 @@ TEST_F(BuilderTest, Accessor_Array_Of_Vec) { EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(OpStore %14 %12 %18 = OpAccessChain %17 %14 %16 +%19 = OpLoad %2 %18 +)"); +} + +TEST_F(BuilderTest, Accessor_Array_Of_Array_Of_f32) { + // let pos : array, 3> = array, 3>( + // array(0.0, 0.5), + // array(-0.5, -0.5), + // array(0.5, -0.5)); + // pos[2][1] + + auto* var = + Const("pos", ty.array(ty.vec2(), 3), + Construct(ty.array(ty.vec2(), 3), vec2(0.0f, 0.5f), + vec2(-0.5f, -0.5f), vec2(0.5f, -0.5f))); + + auto* expr = IndexAccessor(IndexAccessor("pos", 2u), 1u); + WrapInFunction(var, expr); + + spirv::Builder& b = Build(); + + b.push_function(Function{}); + ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error(); + EXPECT_EQ(b.GenerateAccessorExpression(expr), 21u) << b.error(); + + EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 +%2 = OpTypeVector %3 2 +%4 = OpTypeInt 32 0 +%5 = OpConstant %4 3 +%1 = OpTypeArray %2 %5 +%6 = OpConstant %3 0 +%7 = OpConstant %3 0.5 +%8 = OpConstantComposite %2 %6 %7 +%9 = OpConstant %3 -0.5 +%10 = OpConstantComposite %2 %9 %9 +%11 = OpConstantComposite %2 %7 %9 +%12 = OpConstantComposite %1 %8 %10 %11 +%13 = OpTypePointer Function %1 +%15 = OpConstantNull %1 +%16 = OpConstant %4 2 +%17 = OpConstant %4 1 +%19 = OpTypePointer Function %3 +)"); + EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), + R"(%14 = OpVariable %13 Function %15 +)"); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(OpStore %14 %12 +%18 = OpCompositeExtract %3 %14 1 +%20 = OpAccessChain %19 %18 %16 +%21 = OpLoad %3 %20 )"); } diff --git a/src/writer/spirv/builder_ident_expression_test.cc b/src/writer/spirv/builder_ident_expression_test.cc index 821f9e5824..c57b44affd 100644 --- a/src/writer/spirv/builder_ident_expression_test.cc +++ b/src/writer/spirv/builder_ident_expression_test.cc @@ -90,7 +90,7 @@ TEST_F(BuilderTest, IdentifierExpression_FunctionConst) { } TEST_F(BuilderTest, IdentifierExpression_FunctionVar) { - auto* v = Var("var", ty.f32(), ast::StorageClass::kNone); + auto* v = Var("var", ty.f32(), ast::StorageClass::kFunction); auto* expr = Expr("var"); WrapInFunction(v, expr); diff --git a/src/writer/spirv/builder_intrinsic_test.cc b/src/writer/spirv/builder_intrinsic_test.cc index bca5f4af93..d6d8156807 100644 --- a/src/writer/spirv/builder_intrinsic_test.cc +++ b/src/writer/spirv/builder_intrinsic_test.cc @@ -1262,7 +1262,7 @@ INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest, TEST_F(IntrinsicBuilderTest, Call_Modf) { auto* out = Var("out", ty.vec2()); - auto* expr = Call("modf", vec2(1.0f, 2.0f), "out"); + auto* expr = Call("modf", vec2(1.0f, 2.0f), AddressOf("out")); Func("a_func", ast::VariableList{}, ty.void_(), ast::StatementList{ Decl(out), @@ -1306,7 +1306,7 @@ OpFunctionEnd TEST_F(IntrinsicBuilderTest, Call_Frexp) { auto* out = Var("out", ty.vec2()); - auto* expr = Call("frexp", vec2(1.0f, 2.0f), "out"); + auto* expr = Call("frexp", vec2(1.0f, 2.0f), AddressOf("out")); Func("a_func", ast::VariableList{}, ty.void_(), ast::StatementList{ Decl(out), diff --git a/test/BUILD.gn b/test/BUILD.gn index 88b158ad29..867e8d7a7d 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -257,6 +257,8 @@ tint_unittests_source_set("tint_unittests_core_src") { "../src/resolver/intrinsic_test.cc", "../src/resolver/is_host_shareable_test.cc", "../src/resolver/is_storeable_test.cc", + "../src/resolver/ptr_ref_test.cc", + "../src/resolver/ptr_ref_validation_test.cc", "../src/resolver/pipeline_overridable_constant_test.cc", "../src/resolver/resolver_test.cc", "../src/resolver/resolver_test_helper.cc", @@ -268,6 +270,8 @@ tint_unittests_source_set("tint_unittests_core_src") { "../src/resolver/type_constructor_validation_test.cc", "../src/resolver/type_validation_test.cc", "../src/resolver/validation_test.cc", + "../src/resolver/var_let_test.cc", + "../src/resolver/var_let_validation_test.cc", "../src/scope_stack_test.cc", "../src/sem/bool_type_test.cc", "../src/sem/depth_texture_type_test.cc", diff --git a/test/access/let/matrix.spvasm.expected.msl b/test/access/let/matrix.spvasm.expected.msl index 0915f03f9a..2f5de98dbc 100644 --- a/test/access/let/matrix.spvasm.expected.msl +++ b/test/access/let/matrix.spvasm.expected.msl @@ -2,7 +2,7 @@ using namespace metal; kernel void tint_symbol() { - const float x_24 = float3x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f))[1u].y; + float const x_24 = float3x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f))[1u].y; return; } diff --git a/test/access/let/matrix.wgsl.expected.msl b/test/access/let/matrix.wgsl.expected.msl index 43c391ada6..f8f945d657 100644 --- a/test/access/let/matrix.wgsl.expected.msl +++ b/test/access/let/matrix.wgsl.expected.msl @@ -2,9 +2,9 @@ using namespace metal; kernel void tint_symbol() { - const float3x3 m = float3x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f)); - const float3 v = m[1]; - const float f = v[1]; + float3x3 const m = float3x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f)); + float3 const v = m[1]; + float const f = v[1]; return; } diff --git a/test/access/let/vector.spvasm b/test/access/let/vector.spvasm index 9de59d29c5..6e52ba920f 100644 --- a/test/access/let/vector.spvasm +++ b/test/access/let/vector.spvasm @@ -3,24 +3,24 @@ ; Generator: Google Tint Compiler; 0 ; Bound: 15 ; Schema: 0 - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpName %main "main" - %void = OpTypeVoid - %1 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 - %float_1 = OpConstant %float 1 - %float_2 = OpConstant %float 2 - %float_3 = OpConstant %float 3 - %10 = OpConstantComposite %v3float %float_1 %float_2 %float_3 - %v2float = OpTypeVector %float 2 - %main = OpFunction %void None %1 - %4 = OpLabel - %11 = OpCompositeExtract %float %10 1 - %13 = OpVectorShuffle %v2float %10 %10 0 2 - %14 = OpVectorShuffle %v3float %10 %10 0 2 1 - OpReturn - OpFunctionEnd + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %float = OpTypeFloat 32 +%v3float = OpTypeVector %float 3 +%float_1 = OpConstant %float 1 +%float_2 = OpConstant %float 2 +%float_3 = OpConstant %float 3 + %10 = OpConstantComposite %v3float %float_1 %float_2 %float_3 +%v2float = OpTypeVector %float 2 + %main = OpFunction %void None %1 + %4 = OpLabel + %11 = OpCompositeExtract %float %10 1 + %13 = OpVectorShuffle %v2float %10 %10 0 2 + %14 = OpVectorShuffle %v3float %10 %10 0 2 1 + OpReturn + OpFunctionEnd diff --git a/test/access/let/vector.spvasm.expected.msl b/test/access/let/vector.spvasm.expected.msl index aa214b4aa4..60e701cd82 100644 --- a/test/access/let/vector.spvasm.expected.msl +++ b/test/access/let/vector.spvasm.expected.msl @@ -2,9 +2,9 @@ using namespace metal; kernel void tint_symbol() { - const float x_11 = float3(1.0f, 2.0f, 3.0f).y; - const float2 x_13 = float2(float3(1.0f, 2.0f, 3.0f).x, float3(1.0f, 2.0f, 3.0f).z); - const float3 x_14 = float3(float3(1.0f, 2.0f, 3.0f).x, float3(1.0f, 2.0f, 3.0f).z, float3(1.0f, 2.0f, 3.0f).y); + float const x_11 = float3(1.0f, 2.0f, 3.0f).y; + float2 const x_13 = float2(float3(1.0f, 2.0f, 3.0f).x, float3(1.0f, 2.0f, 3.0f).z); + float3 const x_14 = float3(float3(1.0f, 2.0f, 3.0f).x, float3(1.0f, 2.0f, 3.0f).z, float3(1.0f, 2.0f, 3.0f).y); return; } diff --git a/test/access/let/vector.wgsl.expected.msl b/test/access/let/vector.wgsl.expected.msl index d2f878e8a8..e690077f53 100644 --- a/test/access/let/vector.wgsl.expected.msl +++ b/test/access/let/vector.wgsl.expected.msl @@ -2,10 +2,10 @@ using namespace metal; kernel void tint_symbol() { - const float3 v = float3(1.0f, 2.0f, 3.0f); - const float scalar = v.y; - const float2 swizzle2 = v.xz; - const float3 swizzle3 = v.xzy; + float3 const v = float3(1.0f, 2.0f, 3.0f); + float const scalar = v.y; + float2 const swizzle2 = v.xz; + float3 const swizzle3 = v.xzy; return; } diff --git a/test/access/var/matrix.spvasm.expected.msl b/test/access/var/matrix.spvasm.expected.msl index 01c32f9977..12a0b73e64 100644 --- a/test/access/var/matrix.spvasm.expected.msl +++ b/test/access/var/matrix.spvasm.expected.msl @@ -3,8 +3,8 @@ using namespace metal; kernel void tint_symbol() { float3x3 m = float3x3(float3(0.0f, 0.0f, 0.0f), float3(0.0f, 0.0f, 0.0f), float3(0.0f, 0.0f, 0.0f)); - const float3 x_15 = m[1]; - const float x_16 = x_15.y; + float3 const x_15 = m[1]; + float const x_16 = x_15.y; return; } diff --git a/test/access/var/matrix.wgsl.expected.msl b/test/access/var/matrix.wgsl.expected.msl index ef02f470be..c577ac11f5 100644 --- a/test/access/var/matrix.wgsl.expected.msl +++ b/test/access/var/matrix.wgsl.expected.msl @@ -3,8 +3,8 @@ using namespace metal; kernel void tint_symbol() { float3x3 m = 0.0f; - const float3 v = m[1]; - const float f = v[1]; + float3 const v = m[1]; + float const f = v[1]; return; } diff --git a/test/access/var/vector.spvasm b/test/access/var/vector.spvasm index 11a010c06a..ef665983a7 100644 --- a/test/access/var/vector.spvasm +++ b/test/access/var/vector.spvasm @@ -3,30 +3,30 @@ ; Generator: Google Tint Compiler; 0 ; Bound: 20 ; Schema: 0 - OpCapability Shader - OpMemoryModel Logical GLSL450 - OpEntryPoint GLCompute %main "main" - OpExecutionMode %main LocalSize 1 1 1 - OpName %main "main" - OpName %v "v" - %void = OpTypeVoid - %1 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v3float = OpTypeVector %float 3 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %v "v" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v3float = OpTypeVector %float 3 %_ptr_Function_v3float = OpTypePointer Function %v3float - %9 = OpConstantNull %v3float - %uint = OpTypeInt 32 0 - %uint_1 = OpConstant %uint 1 -%_ptr_Function_float = OpTypePointer Function %float - %v2float = OpTypeVector %float 2 - %main = OpFunction %void None %1 - %4 = OpLabel - %v = OpVariable %_ptr_Function_v3float Function %9 - %13 = OpAccessChain %_ptr_Function_float %v %uint_1 - %14 = OpLoad %float %13 - %16 = OpLoad %v3float %v - %17 = OpVectorShuffle %v2float %16 %16 0 2 - %18 = OpLoad %v3float %v - %19 = OpVectorShuffle %v3float %18 %18 0 2 1 - OpReturn - OpFunctionEnd + %9 = OpConstantNull %v3float + %uint = OpTypeInt 32 0 + %uint_1 = OpConstant %uint 1 + %_ptr_Function_float = OpTypePointer Function %float + %v2float = OpTypeVector %float 2 + %main = OpFunction %void None %1 + %4 = OpLabel + %v = OpVariable %_ptr_Function_v3float Function %9 + %13 = OpAccessChain %_ptr_Function_float %v %uint_1 + %14 = OpLoad %float %13 + %16 = OpLoad %v3float %v + %17 = OpVectorShuffle %v2float %16 %16 0 2 + %18 = OpLoad %v3float %v + %19 = OpVectorShuffle %v3float %18 %18 0 2 1 + OpReturn + OpFunctionEnd diff --git a/test/access/var/vector.spvasm.expected.msl b/test/access/var/vector.spvasm.expected.msl index 3011d7e543..fb9d00891c 100644 --- a/test/access/var/vector.spvasm.expected.msl +++ b/test/access/var/vector.spvasm.expected.msl @@ -3,11 +3,11 @@ using namespace metal; kernel void tint_symbol() { float3 v = float3(0.0f, 0.0f, 0.0f); - const float x_14 = v.y; - const float3 x_16 = v; - const float2 x_17 = float2(x_16.x, x_16.z); - const float3 x_18 = v; - const float3 x_19 = float3(x_18.x, x_18.z, x_18.y); + float const x_14 = v.y; + float3 const x_16 = v; + float2 const x_17 = float2(x_16.x, x_16.z); + float3 const x_18 = v; + float3 const x_19 = float3(x_18.x, x_18.z, x_18.y); return; } diff --git a/test/access/var/vector.wgsl.expected.msl b/test/access/var/vector.wgsl.expected.msl index 62c927e96e..542eae7613 100644 --- a/test/access/var/vector.wgsl.expected.msl +++ b/test/access/var/vector.wgsl.expected.msl @@ -3,9 +3,9 @@ using namespace metal; kernel void tint_symbol() { float3 v = 0.0f; - const float scalar = v.y; - const float2 swizzle2 = v.xz; - const float3 swizzle3 = v.xzy; + float const scalar = v.y; + float2 const swizzle2 = v.xz; + float3 const swizzle3 = v.xzy; return; } diff --git a/test/bug/tint/749.spvasm.expected.spvasm b/test/bug/tint/749.spvasm.expected.spvasm index d7f35932fe..ae34237be5 100644 --- a/test/bug/tint/749.spvasm.expected.spvasm +++ b/test/bug/tint/749.spvasm.expected.spvasm @@ -1,5 +1,2129 @@ -SKIP: - -Validation Failure: - 1:1: OpLoad Pointer '51[%51]' is not a logical pointer. - %52 = OpLoad %int %51 +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 1887 +; Schema: 0 + OpCapability Shader + %1759 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %x_GLF_color + OpExecutionMode %main OriginUpperLeft + OpName %QuicksortObject "QuicksortObject" + OpMemberName %QuicksortObject 0 "numbers" + OpName %obj "obj" + OpName %gl_FragCoord "gl_FragCoord" + OpName %buf0 "buf0" + OpMemberName %buf0 0 "resolution" + OpName %x_188 "x_188" + OpName %x_GLF_color "x_GLF_color" + OpName %swap_i1_i1_ "swap_i1_i1_" + OpName %i "i" + OpName %j "j" + OpName %temp "temp" + OpName %performPartition_i1_i1_ "performPartition_i1_i1_" + OpName %l "l" + OpName %h "h" + OpName %param_3 "param_3" + OpName %i_1 "i_1" + OpName %j_1 "j_1" + OpName %param_2 "param_2" + OpName %param_1 "param_1" + OpName %param "param" + OpName %pivot "pivot" + OpName %x_537 "x_537" + OpName %x_538 "x_538" + OpName %quicksort_ "quicksort_" + OpName %param_4 "param_4" + OpName %h_1 "h_1" + OpName %p "p" + OpName %l_1 "l_1" + OpName %top "top" + OpName %stack "stack" + OpName %param_5 "param_5" + OpName %main "main" + OpName %color "color" + OpName %i_2 "i_2" + OpName %uv "uv" + OpMemberDecorate %QuicksortObject 0 Offset 0 + OpDecorate %_arr_int_uint_10 ArrayStride 4 + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpDecorate %buf0 Block + OpMemberDecorate %buf0 0 Offset 0 + OpDecorate %x_188 DescriptorSet 0 + OpDecorate %x_188 Binding 0 + OpDecorate %x_GLF_color Location 0 + %int = OpTypeInt 32 1 + %uint = OpTypeInt 32 0 + %uint_10 = OpConstant %uint 10 +%_arr_int_uint_10 = OpTypeArray %int %uint_10 +%QuicksortObject = OpTypeStruct %_arr_int_uint_10 +%_ptr_Private_QuicksortObject = OpTypePointer Private %QuicksortObject + %8 = OpConstantNull %QuicksortObject + %obj = OpVariable %_ptr_Private_QuicksortObject Private %8 + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input + %v2float = OpTypeVector %float 2 + %buf0 = OpTypeStruct %v2float +%_ptr_Uniform_buf0 = OpTypePointer Uniform %buf0 + %x_188 = OpVariable %_ptr_Uniform_buf0 Uniform +%_ptr_Output_v4float = OpTypePointer Output %v4float + %19 = OpConstantNull %v4float +%x_GLF_color = OpVariable %_ptr_Output_v4float Output %19 + %void = OpTypeVoid +%_ptr_Function_int = OpTypePointer Function %int + %20 = OpTypeFunction %void %_ptr_Function_int %_ptr_Function_int + %28 = OpConstantNull %int + %int_0 = OpConstant %int 0 + %v3float = OpTypeVector %float 3 + %float_1 = OpConstant %float 1 + %float_2 = OpConstant %float 2 + %float_3 = OpConstant %float 3 + %35 = OpConstantComposite %v3float %float_1 %float_2 %float_3 + %uint_0 = OpConstant %uint 0 +%_ptr_Private_int = OpTypePointer Private %int + %103 = OpConstantComposite %_arr_int_uint_10 %int_0 %int_0 %int_0 %int_0 %int_0 %int_0 %int_0 %int_0 %int_0 %int_0 + %104 = OpConstantComposite %QuicksortObject %103 + %157 = OpTypeFunction %int %_ptr_Function_int %_ptr_Function_int +%_ptr_Function_v2float = OpTypePointer Function %v2float + %171 = OpConstantNull %v2float +%_ptr_Function_v3float = OpTypePointer Function %v3float + %174 = OpConstantNull %v3float + %uint_1 = OpConstant %uint 1 + %int_10 = OpConstant %int 10 +%_ptr_Function_float = OpTypePointer Function %float + %bool = OpTypeBool + %int_1 = OpConstant %int 1 + %426 = OpTypeFunction %void +%_ptr_Function__arr_int_uint_10 = OpTypePointer Function %_arr_int_uint_10 + %436 = OpConstantNull %_arr_int_uint_10 + %int_9 = OpConstant %int 9 + %int_n1 = OpConstant %int -1 + %float_0 = OpConstant %float 0 + %897 = OpConstantComposite %v2float %float_0 %float_0 + %true = OpConstantTrue %bool + %909 = OpConstantComposite %v3float %float_0 %float_0 %float_0 +%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float + %float_0_25 = OpConstant %float 0.25 + %float_0_5 = OpConstant %float 0.5 + %uint_2 = OpConstant %uint 2 + %float_0_75 = OpConstant %float 0.75 + %int_3 = OpConstant %int 3 + %int_4 = OpConstant %int 4 + %uint_5 = OpConstant %uint 5 + %uint_6 = OpConstant %uint 6 + %int_7 = OpConstant %int 7 + %int_8 = OpConstant %int 8 + %uint_9 = OpConstant %uint 9 +%swap_i1_i1_ = OpFunction %void None %20 + %i = OpFunctionParameter %_ptr_Function_int + %j = OpFunctionParameter %_ptr_Function_int + %26 = OpLabel + %temp = OpVariable %_ptr_Function_int Function %28 + %29 = OpLoad %int %temp + OpStore %temp %int_0 + OpStore %temp %29 + %36 = OpCompositeExtract %float %35 2 + %37 = OpCompositeExtract %float %35 1 + %38 = OpCompositeExtract %float %35 2 + %39 = OpCompositeConstruct %v3float %36 %37 %38 + %41 = OpLoad %int %i + OpStore %i %int_0 + OpStore %i %41 + %45 = OpLoad %int %i + %47 = OpLoad %int %j + OpStore %j %int_0 + OpStore %j %47 + %50 = OpCompositeExtract %float %39 1 + %51 = OpCompositeExtract %float %39 0 + %52 = OpCompositeExtract %float %39 1 + %53 = OpCompositeConstruct %v3float %50 %51 %52 + %54 = OpLoad %int %temp + OpStore %temp %int_0 + OpStore %temp %54 + %58 = OpAccessChain %_ptr_Private_int %obj %uint_0 %45 + %60 = OpLoad %int %58 + OpStore %58 %int_0 + OpStore %58 %60 + %64 = OpLoad %int %58 + %65 = OpLoad %int %temp + OpStore %temp %int_0 + OpStore %temp %65 + OpStore %temp %64 + %67 = OpLoad %int %j + OpStore %j %int_0 + OpStore %j %67 + %70 = OpCompositeExtract %float %39 2 + %71 = OpCompositeExtract %float %35 0 + %72 = OpCompositeExtract %float %39 1 + %73 = OpCompositeConstruct %v3float %70 %71 %72 + %75 = OpLoad %int %i + OpStore %i %int_0 + OpStore %i %75 + %79 = OpLoad %int %i + %81 = OpLoad %int %58 + OpStore %58 %int_0 + OpStore %58 %81 + %85 = OpLoad %int %j + %87 = OpLoad %int %i + OpStore %i %int_0 + OpStore %i %87 + %90 = OpCompositeExtract %float %73 0 + %91 = OpCompositeExtract %float %73 2 + %92 = OpCompositeExtract %float %73 2 + %93 = OpCompositeConstruct %v3float %90 %91 %92 + %95 = OpLoad %int %58 + OpStore %58 %int_0 + OpStore %58 %95 + %99 = OpAccessChain %_ptr_Private_int %obj %uint_0 %85 + %101 = OpLoad %int %99 + %102 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %102 + %105 = OpCompositeExtract %float %93 0 + %106 = OpCompositeExtract %float %93 0 + %107 = OpCompositeConstruct %v2float %105 %106 + %109 = OpAccessChain %_ptr_Private_int %obj %uint_0 %79 + %110 = OpCompositeExtract %float %53 0 + %111 = OpCompositeExtract %float %53 2 + %112 = OpCompositeExtract %float %53 0 + %113 = OpCompositeConstruct %v3float %110 %111 %112 + OpStore %109 %101 + %115 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %115 + %116 = OpCompositeExtract %float %93 1 + %117 = OpCompositeExtract %float %93 2 + %118 = OpCompositeExtract %float %93 0 + %119 = OpCompositeConstruct %v3float %116 %117 %118 + %121 = OpLoad %int %i + OpStore %i %int_0 + OpStore %i %121 + %125 = OpLoad %int %j + %126 = OpLoad %int %temp + OpStore %temp %int_0 + OpStore %temp %126 + %127 = OpCompositeExtract %float %119 2 + %128 = OpCompositeExtract %float %119 1 + %129 = OpCompositeConstruct %v2float %127 %128 + %131 = OpLoad %int %99 + OpStore %99 %int_0 + OpStore %99 %131 + %134 = OpLoad %int %temp + %136 = OpLoad %int %j + OpStore %j %int_0 + OpStore %j %136 + %139 = OpCompositeExtract %float %107 0 + %140 = OpCompositeExtract %float %93 1 + %141 = OpCompositeExtract %float %93 0 + %142 = OpCompositeConstruct %v3float %139 %140 %141 + %144 = OpLoad %int %109 + OpStore %109 %int_0 + OpStore %109 %144 + %147 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %147 + %148 = OpCompositeExtract %float %113 0 + %149 = OpCompositeExtract %float %113 1 + %150 = OpCompositeExtract %float %113 0 + %151 = OpCompositeConstruct %v3float %148 %149 %150 + %153 = OpLoad %int %99 + OpStore %99 %int_0 + OpStore %99 %153 + %156 = OpAccessChain %_ptr_Private_int %obj %uint_0 %125 + OpStore %156 %134 + OpReturn + OpFunctionEnd +%performPartition_i1_i1_ = OpFunction %int None %157 + %l = OpFunctionParameter %_ptr_Function_int + %h = OpFunctionParameter %_ptr_Function_int + %161 = OpLabel + %param_3 = OpVariable %_ptr_Function_int Function %28 + %i_1 = OpVariable %_ptr_Function_int Function %28 + %j_1 = OpVariable %_ptr_Function_int Function %28 + %param_2 = OpVariable %_ptr_Function_int Function %28 + %param_1 = OpVariable %_ptr_Function_int Function %28 + %param = OpVariable %_ptr_Function_int Function %28 + %pivot = OpVariable %_ptr_Function_int Function %28 + %x_537 = OpVariable %_ptr_Function_v2float Function %171 + %x_538 = OpVariable %_ptr_Function_v3float Function %174 + %176 = OpLoad %int %h + OpStore %h %int_0 + OpStore %h %176 + %180 = OpLoad %int %h + %182 = OpLoad %int %l + OpStore %l %int_0 + OpStore %l %182 + %186 = OpAccessChain %_ptr_Private_int %obj %uint_0 %180 + %188 = OpLoad %int %186 + OpStore %186 %int_0 + OpStore %186 %188 + %192 = OpLoad %int %186 + %193 = OpLoad %int %param_3 + OpStore %param_3 %int_0 + OpStore %param_3 %193 + %194 = OpCompositeExtract %float %35 2 + %195 = OpCompositeExtract %float %35 0 + %196 = OpCompositeExtract %float %35 2 + %197 = OpCompositeConstruct %v3float %194 %195 %196 + %198 = OpLoad %int %param_1 + OpStore %param_1 %int_0 + OpStore %param_1 %198 + OpStore %pivot %192 + %200 = OpLoad %int %l + %202 = OpLoad %int %h + OpStore %h %int_0 + OpStore %h %202 + %205 = OpLoad %int %j_1 + OpStore %j_1 %int_0 + OpStore %j_1 %205 + %206 = OpCompositeExtract %float %197 1 + %207 = OpCompositeExtract %float %197 2 + %208 = OpCompositeExtract %float %197 1 + %209 = OpCompositeConstruct %v3float %206 %207 %208 + %211 = OpLoad %int %l + OpStore %l %int_0 + OpStore %l %211 + %214 = OpBitcast %int %uint_1 + %216 = OpISub %int %200 %214 + OpStore %i_1 %216 + %218 = OpLoad %int %l + %219 = OpCompositeExtract %float %197 0 + %220 = OpCompositeExtract %float %197 2 + %221 = OpCompositeExtract %float %209 0 + %222 = OpCompositeConstruct %v3float %219 %220 %221 + OpStore %j_1 %int_10 + %224 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %224 + OpBranch %225 + %225 = OpLabel + OpLoopMerge %226 %227 None + OpBranch %228 + %228 = OpLabel + %229 = OpLoad %int %pivot + OpStore %pivot %int_0 + OpStore %pivot %229 + %230 = OpLoad %int %param_1 + OpStore %param_1 %int_0 + OpStore %param_1 %230 + %231 = OpLoad %int %j_1 + %232 = OpLoad %int %pivot + OpStore %pivot %int_0 + OpStore %pivot %232 + %233 = OpCompositeExtract %float %35 1 + %234 = OpCompositeExtract %float %35 2 + %235 = OpCompositeConstruct %v2float %233 %234 + OpStore %x_537 %235 + %236 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %236 + %238 = OpLoad %int %h + %240 = OpLoad %int %h + OpStore %h %int_0 + OpStore %h %240 + %243 = OpLoad %int %param + OpStore %param %int_0 + OpStore %param %243 + %244 = OpLoad %int %j_1 + OpStore %j_1 %int_0 + OpStore %j_1 %244 + %245 = OpCompositeExtract %float %197 0 + %247 = OpAccessChain %_ptr_Function_float %x_537 %uint_1 + %248 = OpLoad %float %247 + %249 = OpCompositeExtract %float %197 2 + %250 = OpCompositeConstruct %v3float %245 %248 %249 + OpStore %x_538 %250 + %251 = OpLoad %int %param + OpStore %param %int_0 + OpStore %param %251 + %252 = OpBitcast %int %uint_1 + %253 = OpISub %int %238 %252 + %254 = OpSLessThanEqual %bool %231 %253 + OpSelectionMerge %256 None + OpBranchConditional %254 %257 %258 + %257 = OpLabel + OpBranch %256 + %258 = OpLabel + OpBranch %226 + %256 = OpLabel + %259 = OpLoad %int %j_1 + %261 = OpLoad %int %186 + OpStore %186 %int_0 + OpStore %186 %261 + %265 = OpAccessChain %_ptr_Private_int %obj %uint_0 %259 + %267 = OpLoad %int %h + OpStore %h %int_0 + OpStore %h %267 + %270 = OpAccessChain %_ptr_Function_float %x_537 %uint_0 + %271 = OpLoad %float %270 + %272 = OpCompositeExtract %float %209 2 + %273 = OpAccessChain %_ptr_Function_float %x_537 %uint_0 + %274 = OpLoad %float %273 + %275 = OpCompositeConstruct %v3float %271 %272 %274 + %276 = OpLoad %int %param_1 + OpStore %param_1 %int_0 + OpStore %param_1 %276 + %278 = OpLoad %int %265 + %279 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %279 + %280 = OpLoad %int %pivot + %281 = OpCompositeExtract %float %35 1 + %282 = OpCompositeExtract %float %197 2 + %283 = OpCompositeConstruct %v2float %281 %282 + %284 = OpLoad %int %i_1 + OpStore %i_1 %int_0 + OpStore %i_1 %284 + %286 = OpLoad %int %l + OpStore %l %int_0 + OpStore %l %286 + %289 = OpCompositeExtract %float %197 1 + %290 = OpCompositeExtract %float %197 0 + %291 = OpCompositeExtract %float %197 1 + %292 = OpCompositeConstruct %v3float %289 %290 %291 + %293 = OpLoad %int %pivot + OpStore %pivot %int_0 + OpStore %pivot %293 + %294 = OpSLessThanEqual %bool %278 %280 + OpSelectionMerge %295 None + OpBranchConditional %294 %296 %295 + %296 = OpLabel + %297 = OpCompositeExtract %float %292 2 + %298 = OpCompositeExtract %float %292 0 + %299 = OpCompositeExtract %float %292 0 + %300 = OpCompositeConstruct %v3float %297 %298 %299 + %301 = OpLoad %int %param_3 + OpStore %param_3 %int_0 + OpStore %param_3 %301 + %302 = OpLoad %int %i_1 + %303 = OpLoad %int %pivot + OpStore %pivot %int_0 + OpStore %pivot %303 + %304 = OpCompositeExtract %float %275 0 + %305 = OpCompositeExtract %float %292 1 + %306 = OpCompositeConstruct %v2float %304 %305 + %307 = OpLoad %int %i_1 + OpStore %i_1 %int_0 + OpStore %i_1 %307 + %308 = OpLoad %int %param + OpStore %param %int_0 + OpStore %param %308 + %309 = OpBitcast %int %uint_1 + %310 = OpIAdd %int %302 %309 + OpStore %i_1 %310 + %312 = OpLoad %int %l + OpStore %l %int_0 + OpStore %l %312 + %315 = OpCompositeExtract %float %35 2 + %316 = OpCompositeExtract %float %35 1 + %317 = OpCompositeExtract %float %283 0 + %318 = OpCompositeConstruct %v3float %315 %316 %317 + %319 = OpLoad %int %i_1 + %320 = OpAccessChain %_ptr_Function_float %x_537 %uint_1 + %321 = OpLoad %float %320 + %322 = OpAccessChain %_ptr_Function_float %x_538 %uint_0 + %323 = OpLoad %float %322 + %324 = OpCompositeConstruct %v2float %321 %323 + %325 = OpLoad %int %param + OpStore %param %int_0 + OpStore %param %325 + OpStore %param %319 + %326 = OpLoad %int %param + OpStore %param %int_0 + OpStore %param %326 + %327 = OpCompositeExtract %float %324 0 + %328 = OpCompositeExtract %float %324 0 + %329 = OpCompositeConstruct %v2float %327 %328 + %330 = OpLoad %int %i_1 + OpStore %i_1 %int_0 + OpStore %i_1 %330 + %331 = OpLoad %int %j_1 + OpStore %param_1 %331 + %332 = OpLoad %int %param_3 + OpStore %param_3 %int_0 + OpStore %param_3 %332 + %333 = OpFunctionCall %void %swap_i1_i1_ %param %param_1 + %336 = OpLoad %int %param_1 + OpStore %param_1 %int_0 + OpStore %param_1 %336 + OpBranch %295 + %295 = OpLabel + %337 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %337 + OpBranch %227 + %227 = OpLabel + %339 = OpLoad %int %h + OpStore %h %int_0 + OpStore %h %339 + %342 = OpLoad %int %j_1 + %344 = OpLoad %int %h + OpStore %h %int_0 + OpStore %h %344 + %347 = OpCompositeExtract %float %275 0 + %348 = OpCompositeExtract %float %292 2 + %349 = OpCompositeExtract %float %292 2 + %350 = OpCompositeConstruct %v3float %347 %348 %349 + %352 = OpLoad %int %265 + OpStore %265 %int_0 + OpStore %265 %352 + %355 = OpLoad %int %param + OpStore %param %int_0 + OpStore %param %355 + %357 = OpIAdd %int %int_1 %342 + OpStore %j_1 %357 + %358 = OpLoad %int %param_1 + OpStore %param_1 %int_0 + OpStore %param_1 %358 + %359 = OpCompositeExtract %float %292 1 + %360 = OpCompositeExtract %float %292 2 + %361 = OpCompositeExtract %float %292 0 + %362 = OpCompositeConstruct %v3float %359 %360 %361 + %364 = OpLoad %int %265 + OpStore %265 %int_0 + OpStore %265 %364 + OpBranch %225 + %226 = OpLabel + %367 = OpLoad %int %i_1 + %369 = OpLoad %int %186 + OpStore %186 %int_0 + OpStore %186 %369 + %372 = OpCompositeExtract %float %197 0 + %373 = OpCompositeExtract %float %197 1 + %374 = OpCompositeConstruct %v2float %372 %373 + %375 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %375 + %377 = OpLoad %int %h + OpStore %h %int_0 + OpStore %h %377 + %380 = OpIAdd %int %int_1 %367 + OpStore %i_1 %380 + %381 = OpLoad %int %param_1 + OpStore %param_1 %int_0 + OpStore %param_1 %381 + %382 = OpLoad %int %i_1 + %383 = OpLoad %int %j_1 + OpStore %j_1 %int_0 + OpStore %j_1 %383 + %384 = OpCompositeExtract %float %197 0 + %385 = OpCompositeExtract %float %197 0 + %386 = OpCompositeConstruct %v2float %384 %385 + %387 = OpLoad %int %param_1 + OpStore %param_1 %int_0 + OpStore %param_1 %387 + OpStore %param_2 %382 + %388 = OpCompositeExtract %float %197 1 + %389 = OpCompositeExtract %float %222 0 + %390 = OpCompositeConstruct %v2float %388 %389 + %391 = OpLoad %int %pivot + OpStore %pivot %int_0 + OpStore %pivot %391 + %393 = OpLoad %int %h + %394 = OpCompositeExtract %float %386 0 + %395 = OpCompositeExtract %float %374 1 + %396 = OpCompositeConstruct %v2float %394 %395 + %398 = OpLoad %int %h + OpStore %h %int_0 + OpStore %h %398 + OpStore %param_3 %393 + %401 = OpLoad %int %i_1 + OpStore %i_1 %int_0 + OpStore %i_1 %401 + %402 = OpCompositeExtract %float %374 1 + %403 = OpCompositeExtract %float %396 0 + %404 = OpCompositeConstruct %v2float %402 %403 + %406 = OpLoad %int %h + OpStore %h %int_0 + OpStore %h %406 + %409 = OpFunctionCall %void %swap_i1_i1_ %param_2 %param_3 + %413 = OpLoad %int %l + OpStore %l %int_0 + OpStore %l %413 + %416 = OpCompositeExtract %float %222 2 + %417 = OpCompositeExtract %float %35 1 + %418 = OpCompositeConstruct %v2float %416 %417 + %419 = OpLoad %int %param_1 + OpStore %param_1 %int_0 + OpStore %param_1 %419 + %420 = OpLoad %int %i_1 + %421 = OpLoad %int %param + OpStore %param %int_0 + OpStore %param %421 + %422 = OpCompositeExtract %float %197 1 + %423 = OpCompositeExtract %float %197 0 + %424 = OpCompositeConstruct %v2float %422 %423 + %425 = OpLoad %int %j_1 + OpStore %j_1 %int_0 + OpStore %j_1 %425 + OpReturnValue %420 + OpFunctionEnd + %quicksort_ = OpFunction %void None %426 + %428 = OpLabel + %param_4 = OpVariable %_ptr_Function_int Function %28 + %h_1 = OpVariable %_ptr_Function_int Function %28 + %p = OpVariable %_ptr_Function_int Function %28 + %l_1 = OpVariable %_ptr_Function_int Function %28 + %top = OpVariable %_ptr_Function_int Function %28 + %stack = OpVariable %_ptr_Function__arr_int_uint_10 Function %436 + %param_5 = OpVariable %_ptr_Function_int Function %28 + OpStore %l_1 %int_0 + %438 = OpLoad %int %param_5 + OpStore %param_5 %int_0 + OpStore %param_5 %438 + OpStore %h_1 %int_9 + %440 = OpLoad %_arr_int_uint_10 %stack + OpStore %stack %103 + OpStore %stack %440 + %441 = OpCompositeExtract %float %35 1 + %442 = OpCompositeExtract %float %35 1 + %443 = OpCompositeConstruct %v2float %441 %442 + %444 = OpLoad %int %param_5 + OpStore %param_5 %int_0 + OpStore %param_5 %444 + OpStore %top %int_n1 + %446 = OpLoad %int %p + OpStore %p %int_0 + OpStore %p %446 + %447 = OpLoad %int %top + %448 = OpCompositeExtract %float %35 0 + %449 = OpCompositeExtract %float %35 0 + %450 = OpCompositeConstruct %v2float %448 %449 + %451 = OpLoad %int %p + OpStore %p %int_0 + OpStore %p %451 + %452 = OpBitcast %int %uint_1 + %453 = OpIAdd %int %447 %452 + %454 = OpLoad %int %top + OpStore %top %int_0 + OpStore %top %454 + %455 = OpCompositeExtract %float %443 1 + %456 = OpCompositeExtract %float %450 1 + %457 = OpCompositeConstruct %v2float %455 %456 + %458 = OpLoad %int %param_4 + OpStore %param_4 %int_0 + OpStore %param_4 %458 + OpStore %top %453 + %459 = OpLoad %int %h_1 + OpStore %h_1 %int_0 + OpStore %h_1 %459 + %460 = OpCompositeExtract %float %450 1 + %461 = OpCompositeExtract %float %450 0 + %462 = OpCompositeExtract %float %450 0 + %463 = OpCompositeConstruct %v3float %460 %461 %462 + %464 = OpLoad %int %param_4 + OpStore %param_4 %int_0 + OpStore %param_4 %464 + %465 = OpLoad %int %l_1 + %466 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %466 + %467 = OpCompositeExtract %float %463 1 + %468 = OpCompositeExtract %float %463 0 + %469 = OpCompositeExtract %float %450 0 + %470 = OpCompositeConstruct %v3float %467 %468 %469 + %472 = OpAccessChain %_ptr_Function_int %stack %453 + %473 = OpLoad %_arr_int_uint_10 %stack + OpStore %stack %103 + OpStore %stack %473 + %474 = OpCompositeExtract %float %443 1 + %475 = OpCompositeExtract %float %443 1 + %476 = OpCompositeExtract %float %443 1 + %477 = OpCompositeConstruct %v3float %474 %475 %476 + %478 = OpLoad %int %l_1 + OpStore %l_1 %int_0 + OpStore %l_1 %int_0 + OpStore %472 %465 + %480 = OpLoad %int %param_5 + OpStore %param_5 %int_0 + OpStore %param_5 %480 + %481 = OpLoad %int %top + %482 = OpLoad %int %param_4 + OpStore %param_4 %int_0 + OpStore %param_4 %482 + %483 = OpCompositeExtract %float %35 2 + %484 = OpCompositeExtract %float %457 1 + %485 = OpCompositeExtract %float %35 1 + %486 = OpCompositeConstruct %v3float %483 %484 %485 + %488 = OpLoad %int %472 + OpStore %472 %int_0 + OpStore %472 %488 + %491 = OpIAdd %int %481 %int_1 + %493 = OpLoad %int %472 + OpStore %472 %int_0 + OpStore %472 %493 + %496 = OpCompositeExtract %float %463 0 + %497 = OpCompositeExtract %float %463 2 + %498 = OpCompositeExtract %float %443 1 + %499 = OpCompositeConstruct %v3float %496 %497 %498 + OpStore %top %491 + %500 = OpLoad %int %param_4 + OpStore %param_4 %int_0 + OpStore %param_4 %500 + %501 = OpLoad %int %h_1 + %502 = OpLoad %int %param_4 + OpStore %param_4 %int_0 + OpStore %param_4 %502 + %503 = OpCompositeExtract %float %457 0 + %504 = OpCompositeExtract %float %477 0 + %505 = OpCompositeExtract %float %457 1 + %506 = OpCompositeConstruct %v3float %503 %504 %505 + %507 = OpLoad %int %l_1 + OpStore %l_1 %int_0 + OpStore %l_1 %507 + %509 = OpAccessChain %_ptr_Function_int %stack %491 + %510 = OpLoad %int %param_5 + OpStore %param_5 %int_0 + OpStore %param_5 %510 + %511 = OpCompositeExtract %float %506 2 + %512 = OpCompositeExtract %float %506 2 + %513 = OpCompositeConstruct %v2float %511 %512 + %514 = OpLoad %int %p + OpStore %p %int_0 + OpStore %p %514 + OpStore %509 %501 + OpBranch %516 + %516 = OpLabel + OpLoopMerge %517 %518 None + OpBranch %519 + %519 = OpLabel + %520 = OpCompositeExtract %float %499 0 + %521 = OpCompositeExtract %float %499 0 + %522 = OpCompositeExtract %float %499 0 + %523 = OpCompositeConstruct %v3float %520 %521 %522 + %524 = OpLoad %int %h_1 + OpStore %h_1 %int_0 + OpStore %h_1 %524 + %525 = OpLoad %_arr_int_uint_10 %stack + OpStore %stack %103 + OpStore %stack %525 + %526 = OpLoad %int %top + %527 = OpLoad %_arr_int_uint_10 %stack + OpStore %stack %103 + OpStore %stack %527 + %528 = OpCompositeExtract %float %457 0 + %529 = OpCompositeExtract %float %506 2 + %530 = OpCompositeConstruct %v2float %528 %529 + %531 = OpLoad %int %param_4 + OpStore %param_4 %int_0 + OpStore %param_4 %531 + %532 = OpBitcast %int %uint_0 + %533 = OpSGreaterThanEqual %bool %526 %532 + OpSelectionMerge %534 None + OpBranchConditional %533 %535 %536 + %535 = OpLabel + OpBranch %534 + %536 = OpLabel + OpBranch %517 + %534 = OpLabel + %537 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %537 + %538 = OpCompositeExtract %float %463 1 + %539 = OpCompositeExtract %float %463 0 + %540 = OpCompositeExtract %float %499 1 + %541 = OpCompositeConstruct %v3float %538 %539 %540 + %542 = OpLoad %int %param_4 + OpStore %param_4 %int_0 + OpStore %param_4 %542 + %543 = OpLoad %int %top + %544 = OpCompositeExtract %float %513 0 + %545 = OpCompositeExtract %float %530 1 + %546 = OpCompositeExtract %float %513 0 + %547 = OpCompositeConstruct %v3float %544 %545 %546 + %548 = OpLoad %int %h_1 + OpStore %h_1 %int_0 + OpStore %h_1 %548 + %549 = OpCompositeExtract %float %443 0 + %550 = OpCompositeExtract %float %443 0 + %551 = OpCompositeConstruct %v2float %549 %550 + %552 = OpLoad %int %p + OpStore %p %int_0 + OpStore %p %552 + %553 = OpBitcast %int %uint_1 + %554 = OpISub %int %543 %553 + OpStore %top %554 + %555 = OpLoad %int %p + OpStore %p %int_0 + OpStore %p %555 + %557 = OpAccessChain %_ptr_Function_int %stack %543 + %559 = OpLoad %int %472 + OpStore %472 %int_0 + OpStore %472 %559 + %563 = OpLoad %int %557 + %564 = OpLoad %_arr_int_uint_10 %stack + OpStore %stack %103 + OpStore %stack %564 + %565 = OpCompositeExtract %float %463 1 + %566 = OpCompositeExtract %float %463 0 + %567 = OpCompositeExtract %float %506 1 + %568 = OpCompositeConstruct %v3float %565 %566 %567 + %569 = OpLoad %int %l_1 + OpStore %l_1 %int_0 + OpStore %l_1 %569 + OpStore %h_1 %563 + %570 = OpLoad %_arr_int_uint_10 %stack + OpStore %stack %103 + OpStore %stack %570 + %571 = OpCompositeExtract %float %486 1 + %572 = OpCompositeExtract %float %477 1 + %573 = OpCompositeConstruct %v2float %571 %572 + %574 = OpLoad %int %p + OpStore %p %int_0 + OpStore %p %574 + %575 = OpLoad %int %top + %576 = OpLoad %int %param_4 + OpStore %param_4 %int_0 + OpStore %param_4 %576 + %578 = OpLoad %int %509 + OpStore %509 %int_0 + OpStore %509 %578 + %581 = OpCompositeExtract %float %35 1 + %582 = OpCompositeExtract %float %35 2 + %583 = OpCompositeConstruct %v2float %581 %582 + %584 = OpISub %int %575 %int_1 + OpStore %top %584 + %585 = OpLoad %int %param_5 + OpStore %param_5 %int_0 + OpStore %param_5 %585 + %586 = OpCompositeExtract %float %551 1 + %587 = OpCompositeExtract %float %513 0 + %588 = OpCompositeExtract %float %551 1 + %589 = OpCompositeConstruct %v3float %586 %587 %588 + %590 = OpLoad %int %h_1 + OpStore %h_1 %int_0 + OpStore %h_1 %590 + %592 = OpAccessChain %_ptr_Function_int %stack %575 + %593 = OpCompositeExtract %float %506 1 + %594 = OpCompositeExtract %float %506 2 + %595 = OpCompositeConstruct %v2float %593 %594 + %597 = OpLoad %int %509 + OpStore %509 %int_0 + OpStore %509 %597 + %601 = OpLoad %int %592 + %602 = OpLoad %int %p + OpStore %p %int_0 + OpStore %p %602 + %603 = OpCompositeExtract %float %583 1 + %604 = OpCompositeExtract %float %583 1 + %605 = OpCompositeExtract %float %513 0 + %606 = OpCompositeConstruct %v3float %603 %604 %605 + %607 = OpLoad %int %param_5 + OpStore %param_5 %int_0 + OpStore %param_5 %607 + OpStore %l_1 %601 + %608 = OpLoad %int %top + OpStore %top %int_0 + OpStore %top %608 + %609 = OpLoad %int %l_1 + OpStore %param_4 %609 + %611 = OpLoad %int %557 + OpStore %557 %int_0 + OpStore %557 %611 + %614 = OpCompositeExtract %float %547 1 + %615 = OpCompositeExtract %float %547 2 + %616 = OpCompositeConstruct %v2float %614 %615 + %617 = OpLoad %int %h_1 + %618 = OpCompositeExtract %float %457 0 + %619 = OpCompositeExtract %float %35 1 + %620 = OpCompositeConstruct %v2float %618 %619 + OpStore %param_5 %617 + %622 = OpLoad %int %509 + OpStore %509 %int_0 + OpStore %509 %622 + %625 = OpFunctionCall %int %performPartition_i1_i1_ %param_4 %param_5 + %628 = OpCompositeExtract %float %530 0 + %629 = OpCompositeExtract %float %541 0 + %630 = OpCompositeConstruct %v2float %628 %629 + %631 = OpLoad %int %param_5 + OpStore %param_5 %int_0 + OpStore %param_5 %631 + OpStore %p %625 + %632 = OpLoad %int %param_4 + OpStore %param_4 %int_0 + OpStore %param_4 %632 + %633 = OpLoad %int %p + %634 = OpLoad %int %h_1 + OpStore %h_1 %int_0 + OpStore %h_1 %634 + %635 = OpCompositeExtract %float %541 1 + %636 = OpCompositeExtract %float %541 1 + %637 = OpCompositeConstruct %v2float %635 %636 + %638 = OpLoad %int %l_1 + OpStore %l_1 %int_0 + OpStore %l_1 %638 + %639 = OpLoad %int %h_1 + OpStore %h_1 %int_0 + OpStore %h_1 %639 + %640 = OpLoad %int %l_1 + %642 = OpLoad %int %557 + OpStore %557 %int_0 + OpStore %557 %642 + %645 = OpLoad %int %h_1 + OpStore %h_1 %int_0 + OpStore %h_1 %645 + %646 = OpCompositeExtract %float %530 1 + %647 = OpCompositeExtract %float %583 0 + %648 = OpCompositeConstruct %v2float %646 %647 + %650 = OpLoad %int %509 + OpStore %509 %int_0 + OpStore %509 %650 + %653 = OpBitcast %int %uint_1 + %654 = OpISub %int %633 %653 + %655 = OpSGreaterThan %bool %654 %640 + OpSelectionMerge %656 None + OpBranchConditional %655 %657 %656 + %657 = OpLabel + %658 = OpLoad %int %param_4 + OpStore %param_4 %int_0 + OpStore %param_4 %658 + %659 = OpLoad %int %top + %660 = OpCompositeExtract %float %568 1 + %661 = OpCompositeExtract %float %443 1 + %662 = OpCompositeConstruct %v2float %660 %661 + %664 = OpLoad %int %509 + OpStore %509 %int_0 + OpStore %509 %664 + %667 = OpLoad %_arr_int_uint_10 %stack + OpStore %stack %103 + OpStore %stack %667 + %668 = OpCompositeExtract %float %547 2 + %669 = OpCompositeExtract %float %547 1 + %670 = OpCompositeConstruct %v2float %668 %669 + %671 = OpCompositeExtract %float %637 1 + %672 = OpCompositeExtract %float %616 0 + %673 = OpCompositeExtract %float %616 0 + %674 = OpCompositeConstruct %v3float %671 %672 %673 + %675 = OpLoad %int %l_1 + %677 = OpLoad %int %592 + OpStore %592 %int_0 + OpStore %592 %677 + %680 = OpCompositeExtract %float %506 0 + %681 = OpCompositeExtract %float %674 0 + %682 = OpCompositeConstruct %v2float %680 %681 + %683 = OpLoad %int %param_5 + OpStore %param_5 %int_0 + OpStore %param_5 %683 + %685 = OpIAdd %int %int_1 %659 + %686 = OpAccessChain %_ptr_Function_int %stack %685 + %688 = OpLoad %int %557 + OpStore %557 %int_0 + OpStore %557 %688 + %691 = OpCompositeExtract %float %523 1 + %692 = OpCompositeExtract %float %523 1 + %693 = OpCompositeExtract %float %499 0 + %694 = OpCompositeConstruct %v3float %691 %692 %693 + %695 = OpLoad %int %param_5 + OpStore %param_5 %int_0 + OpStore %param_5 %695 + OpStore %686 %675 + %697 = OpLoad %int %top + %699 = OpLoad %int %509 + OpStore %509 %int_0 + OpStore %509 %699 + %702 = OpCompositeExtract %float %595 1 + %703 = OpCompositeExtract %float %595 0 + %704 = OpCompositeConstruct %v2float %702 %703 + %706 = OpLoad %int %686 + OpStore %686 %int_0 + OpStore %686 %706 + %710 = OpBitcast %uint %697 + %711 = OpIAdd %uint %uint_1 %710 + %709 = OpBitcast %int %711 + %713 = OpLoad %int %509 + OpStore %509 %int_0 + OpStore %509 %713 + %716 = OpCompositeExtract %float %606 2 + %717 = OpCompositeExtract %float %704 1 + %718 = OpCompositeExtract %float %606 2 + %719 = OpCompositeConstruct %v3float %716 %717 %718 + %720 = OpLoad %int %h_1 + OpStore %h_1 %int_0 + OpStore %h_1 %720 + OpStore %top %709 + %721 = OpLoad %_arr_int_uint_10 %stack + OpStore %stack %103 + OpStore %stack %721 + %722 = OpLoad %int %p + %723 = OpCompositeExtract %float %606 0 + %724 = OpCompositeExtract %float %583 1 + %725 = OpCompositeConstruct %v2float %723 %724 + %727 = OpLoad %int %592 + OpStore %592 %int_0 + OpStore %592 %727 + %731 = OpAccessChain %_ptr_Function_int %stack %709 + %733 = OpLoad %int %592 + OpStore %592 %int_0 + OpStore %592 %733 + %737 = OpBitcast %int %uint_1 + %738 = OpISub %int %722 %737 + OpStore %731 %738 + %740 = OpLoad %int %472 + OpStore %472 %int_0 + OpStore %472 %740 + %743 = OpCompositeExtract %float %547 2 + %744 = OpCompositeExtract %float %547 1 + %745 = OpCompositeConstruct %v2float %743 %744 + %747 = OpLoad %int %731 + OpStore %731 %int_0 + OpStore %731 %747 + OpBranch %656 + %656 = OpLabel + %751 = OpLoad %int %472 + OpStore %472 %int_0 + OpStore %472 %751 + %754 = OpCompositeExtract %float %35 0 + %755 = OpCompositeExtract %float %35 1 + %756 = OpCompositeConstruct %v2float %754 %755 + %757 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %757 + %758 = OpLoad %int %p + %760 = OpLoad %int %592 + OpStore %592 %int_0 + OpStore %592 %760 + %763 = OpCompositeExtract %float %568 2 + %764 = OpCompositeExtract %float %443 0 + %765 = OpCompositeExtract %float %443 1 + %766 = OpCompositeConstruct %v3float %763 %764 %765 + %767 = OpLoad %int %p + OpStore %p %int_0 + OpStore %p %767 + %768 = OpCompositeExtract %float %499 2 + %769 = OpCompositeExtract %float %499 0 + %770 = OpCompositeExtract %float %595 0 + %771 = OpCompositeConstruct %v3float %768 %769 %770 + %773 = OpLoad %int %592 + OpStore %592 %int_0 + OpStore %592 %773 + %776 = OpLoad %int %h_1 + %777 = OpLoad %int %top + OpStore %top %int_0 + OpStore %top %777 + %778 = OpCompositeExtract %float %470 2 + %779 = OpCompositeExtract %float %541 0 + %780 = OpCompositeExtract %float %470 0 + %781 = OpCompositeConstruct %v3float %778 %779 %780 + %783 = OpLoad %int %509 + OpStore %509 %int_0 + OpStore %509 %783 + %786 = OpLoad %int %p + OpStore %p %int_0 + OpStore %p %786 + %788 = OpBitcast %uint %758 + %789 = OpIAdd %uint %uint_1 %788 + %787 = OpBitcast %int %789 + %790 = OpSLessThan %bool %787 %776 + OpSelectionMerge %791 None + OpBranchConditional %790 %792 %791 + %792 = OpLabel + %794 = OpLoad %int %592 + OpStore %592 %int_0 + OpStore %592 %794 + %797 = OpCompositeExtract %float %756 1 + %798 = OpCompositeExtract %float %648 0 + %799 = OpCompositeConstruct %v2float %797 %798 + %800 = OpLoad %int %l_1 + OpStore %l_1 %int_0 + OpStore %l_1 %800 + %801 = OpLoad %int %top + %803 = OpLoad %int %592 + OpStore %592 %int_0 + OpStore %592 %803 + %806 = OpCompositeExtract %float %486 1 + %807 = OpCompositeExtract %float %470 1 + %808 = OpCompositeExtract %float %470 1 + %809 = OpCompositeConstruct %v3float %806 %807 %808 + %810 = OpIAdd %int %801 %int_1 + %811 = OpLoad %int %param_5 + OpStore %param_5 %int_0 + OpStore %param_5 %811 + OpStore %top %810 + %813 = OpLoad %int %592 + OpStore %592 %int_0 + OpStore %592 %813 + %816 = OpLoad %int %p + %817 = OpLoad %int %param_5 + OpStore %param_5 %int_0 + OpStore %param_5 %817 + %818 = OpCompositeExtract %float %470 2 + %819 = OpCompositeExtract %float %470 0 + %820 = OpCompositeExtract %float %541 0 + %821 = OpCompositeConstruct %v3float %818 %819 %820 + %822 = OpLoad %int %p + OpStore %p %int_0 + OpStore %p %822 + %823 = OpCompositeExtract %float %443 0 + %824 = OpCompositeExtract %float %637 0 + %825 = OpCompositeExtract %float %637 0 + %826 = OpCompositeConstruct %v3float %823 %824 %825 + %828 = OpLoad %int %509 + OpStore %509 %int_0 + OpStore %509 %828 + %832 = OpAccessChain %_ptr_Function_int %stack %810 + %834 = OpLoad %int %557 + OpStore %557 %int_0 + OpStore %557 %834 + %837 = OpCompositeExtract %float %499 0 + %838 = OpCompositeExtract %float %499 1 + %839 = OpCompositeConstruct %v2float %837 %838 + %842 = OpBitcast %uint %816 + %843 = OpIAdd %uint %uint_1 %842 + %841 = OpBitcast %int %843 + OpStore %832 %841 + %844 = OpLoad %_arr_int_uint_10 %stack + OpStore %stack %103 + OpStore %stack %844 + %845 = OpLoad %int %top + %847 = OpLoad %int %592 + OpStore %592 %int_0 + OpStore %592 %847 + %850 = OpCompositeExtract %float %513 1 + %851 = OpCompositeExtract %float %821 1 + %852 = OpCompositeConstruct %v2float %850 %851 + %853 = OpLoad %_arr_int_uint_10 %stack + OpStore %stack %103 + OpStore %stack %853 + %854 = OpBitcast %int %uint_1 + %855 = OpIAdd %int %845 %854 + %857 = OpLoad %int %832 + OpStore %832 %int_0 + OpStore %832 %857 + OpStore %top %855 + %860 = OpLoad %int %param_4 + OpStore %param_4 %int_0 + OpStore %param_4 %860 + %861 = OpLoad %int %h_1 + %863 = OpLoad %int %509 + OpStore %509 %int_0 + OpStore %509 %863 + %867 = OpLoad %int %472 + OpStore %472 %int_0 + OpStore %472 %867 + %870 = OpAccessChain %_ptr_Function_int %stack %855 + OpStore %870 %861 + %872 = OpLoad %int %592 + OpStore %592 %int_0 + OpStore %592 %872 + %875 = OpCompositeExtract %float %541 1 + %876 = OpCompositeExtract %float %506 0 + %877 = OpCompositeExtract %float %506 0 + %878 = OpCompositeConstruct %v3float %875 %876 %877 + %879 = OpLoad %int %l_1 + OpStore %l_1 %int_0 + OpStore %l_1 %879 + OpBranch %791 + %791 = OpLabel + %881 = OpLoad %int %509 + OpStore %509 %int_0 + OpStore %509 %881 + OpBranch %518 + %518 = OpLabel + %884 = OpLoad %int %l_1 + OpStore %l_1 %int_0 + OpStore %l_1 %884 + %885 = OpCompositeExtract %float %499 2 + %886 = OpCompositeExtract %float %506 0 + %887 = OpCompositeConstruct %v2float %885 %886 + %888 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %888 + OpBranch %516 + %517 = OpLabel + %889 = OpLoad %int %h_1 + OpStore %h_1 %int_0 + OpStore %h_1 %889 + OpReturn + OpFunctionEnd + %main = OpFunction %void None %426 + %891 = OpLabel + %color = OpVariable %_ptr_Function_v3float Function %174 + %i_2 = OpVariable %_ptr_Function_int Function %28 + %uv = OpVariable %_ptr_Function_v2float Function %171 + %895 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %895 + OpStore %i_2 %int_0 + %898 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %898 + OpSelectionMerge %900 None + OpBranchConditional %true %901 %900 + %901 = OpLabel + %902 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %902 + %903 = OpCompositeExtract %float %35 0 + %904 = OpCompositeExtract %float %35 0 + %905 = OpCompositeConstruct %v2float %903 %904 + %906 = OpLoad %int %i_2 + %907 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %907 + %908 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %908 + %910 = OpCompositeExtract %float %905 1 + %911 = OpCompositeExtract %float %905 1 + %912 = OpCompositeConstruct %v2float %910 %911 + %913 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %913 + OpBranch %900 + %900 = OpLabel + %914 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %914 + %915 = OpCompositeExtract %float %897 0 + %916 = OpCompositeExtract %float %897 0 + %917 = OpCompositeConstruct %v2float %915 %916 + %918 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %918 + %919 = OpFunctionCall %void %quicksort_ + %920 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %920 + %921 = OpLoad %v4float %gl_FragCoord + %922 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %922 + %923 = OpCompositeExtract %float %897 1 + %924 = OpCompositeExtract %float %897 1 + %925 = OpCompositeConstruct %v2float %923 %924 + %926 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %926 + %927 = OpCompositeExtract %float %921 0 + %928 = OpCompositeExtract %float %921 1 + %929 = OpCompositeConstruct %v2float %927 %928 + %930 = OpCompositeExtract %float %929 1 + %931 = OpCompositeExtract %float %917 1 + %932 = OpCompositeExtract %float %917 1 + %933 = OpCompositeConstruct %v3float %930 %931 %932 + %934 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %934 + %935 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %935 + %937 = OpAccessChain %_ptr_Uniform_v2float %x_188 %uint_0 + %938 = OpLoad %v2float %937 + %939 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %939 + %940 = OpCompositeExtract %float %921 1 + %941 = OpCompositeExtract %float %35 2 + %942 = OpCompositeExtract %float %921 3 + %943 = OpCompositeConstruct %v3float %940 %941 %942 + %944 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %944 + %945 = OpFDiv %v2float %929 %938 + %946 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %946 + %947 = OpCompositeExtract %float %925 0 + %948 = OpCompositeExtract %float %929 1 + %949 = OpCompositeConstruct %v2float %947 %948 + %950 = OpLoad %v3float %color + OpStore %color %909 + %951 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %951 + OpStore %color %950 + OpStore %uv %945 + OpStore %color %35 + %952 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %952 + %953 = OpCompositeExtract %float %929 0 + %954 = OpCompositeExtract %float %929 1 + %955 = OpCompositeExtract %float %917 1 + %956 = OpCompositeConstruct %v3float %953 %954 %955 + %957 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %957 + %959 = OpAccessChain %_ptr_Private_int %obj %uint_0 %uint_0 + %961 = OpLoad %int %959 + OpStore %959 %int_0 + OpStore %959 %961 + %965 = OpLoad %int %959 + %966 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %966 + %968 = OpAccessChain %_ptr_Function_float %color %uint_0 + %970 = OpLoad %int %959 + OpStore %959 %int_0 + OpStore %959 %970 + %974 = OpLoad %float %968 + %976 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %976 + %979 = OpCompositeExtract %float %35 2 + %980 = OpCompositeExtract %float %35 1 + %981 = OpCompositeConstruct %v2float %979 %980 + %982 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %982 + %983 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %983 + %985 = OpAccessChain %_ptr_Function_float %color %uint_0 + %986 = OpCompositeExtract %float %956 0 + %987 = OpCompositeExtract %float %949 0 + %988 = OpCompositeExtract %float %949 1 + %989 = OpCompositeConstruct %v3float %986 %987 %988 + %991 = OpConvertSToF %float %965 + %992 = OpFAdd %float %974 %991 + OpStore %985 %992 + %993 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %993 + %995 = OpAccessChain %_ptr_Function_float %uv %uint_0 + %996 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %996 + %997 = OpCompositeExtract %float %921 1 + %998 = OpCompositeExtract %float %921 1 + %999 = OpCompositeConstruct %v2float %997 %998 + %1001 = OpLoad %float %995 + %1002 = OpCompositeExtract %float %945 1 + %1003 = OpCompositeExtract %float %945 0 + %1004 = OpCompositeConstruct %v2float %1002 %1003 + %1006 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1006 + %1009 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %1009 + %1011 = OpFOrdGreaterThan %bool %1001 %float_0_25 + OpSelectionMerge %1012 None + OpBranchConditional %1011 %1013 %1012 + %1013 = OpLabel + %1014 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1014 + %1016 = OpLoad %int %959 + OpStore %959 %int_0 + OpStore %959 %1016 + %1019 = OpCompositeExtract %float %897 1 + %1020 = OpCompositeExtract %float %933 1 + %1021 = OpCompositeExtract %float %933 1 + %1022 = OpCompositeConstruct %v3float %1019 %1020 %1021 + %1024 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1024 + %1027 = OpAccessChain %_ptr_Private_int %obj %uint_0 %int_1 + %1028 = OpLoad %int %1027 + %1029 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %1029 + %1030 = OpCompositeExtract %float %999 0 + %1031 = OpCompositeExtract %float %999 0 + %1032 = OpCompositeConstruct %v2float %1030 %1031 + %1033 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %1033 + %1035 = OpAccessChain %_ptr_Function_float %color %int_0 + %1036 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %1036 + %1037 = OpCompositeExtract %float %35 2 + %1038 = OpCompositeExtract %float %897 1 + %1039 = OpCompositeConstruct %v2float %1037 %1038 + %1040 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1040 + %1042 = OpLoad %float %1035 + %1044 = OpLoad %float %1035 + OpStore %1035 %float_0 + OpStore %1035 %1044 + %1047 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %1047 + %1048 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %1048 + %1049 = OpCompositeExtract %float %999 1 + %1050 = OpCompositeExtract %float %999 1 + %1051 = OpCompositeExtract %float %925 1 + %1052 = OpCompositeConstruct %v3float %1049 %1050 %1051 + %1054 = OpLoad %float %1035 + OpStore %1035 %float_0 + OpStore %1035 %1054 + %1057 = OpAccessChain %_ptr_Function_float %color %uint_0 + %1058 = OpConvertSToF %float %1028 + %1059 = OpFAdd %float %1058 %1042 + OpStore %1057 %1059 + %1061 = OpLoad %int %959 + OpStore %959 %int_0 + OpStore %959 %1061 + OpBranch %1012 + %1012 = OpLabel + %1065 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1065 + %1069 = OpAccessChain %_ptr_Function_float %uv %uint_0 + %1071 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1071 + %1075 = OpLoad %float %1069 + %1077 = OpLoad %float %1069 + OpStore %1069 %float_0 + OpStore %1069 %1077 + %1080 = OpCompositeExtract %float %989 2 + %1081 = OpCompositeExtract %float %989 1 + %1082 = OpCompositeExtract %float %989 1 + %1083 = OpCompositeConstruct %v3float %1080 %1081 %1082 + %1084 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %1084 + %1086 = OpLoad %float %1069 + OpStore %1069 %float_0 + OpStore %1069 %1086 + %1089 = OpCompositeExtract %float %897 1 + %1090 = OpCompositeExtract %float %897 1 + %1091 = OpCompositeConstruct %v2float %1089 %1090 + %1093 = OpLoad %float %1069 + OpStore %1069 %float_0 + OpStore %1069 %1093 + %1097 = OpFOrdGreaterThan %bool %1075 %float_0_5 + OpSelectionMerge %1098 None + OpBranchConditional %1097 %1099 %1098 + %1099 = OpLabel + %1101 = OpLoad %float %1069 + OpStore %1069 %float_0 + OpStore %1069 %1101 + %1104 = OpCompositeExtract %float %917 0 + %1105 = OpCompositeExtract %float %917 0 + %1106 = OpCompositeConstruct %v2float %1104 %1105 + %1108 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1108 + %1113 = OpAccessChain %_ptr_Private_int %obj %uint_0 %uint_2 + %1115 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1115 + %1118 = OpCompositeExtract %float %989 0 + %1119 = OpCompositeExtract %float %989 2 + %1120 = OpCompositeExtract %float %1091 1 + %1121 = OpCompositeConstruct %v3float %1118 %1119 %1120 + %1123 = OpLoad %float %985 + OpStore %985 %float_0 + OpStore %985 %1123 + %1127 = OpLoad %int %1113 + %1129 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1129 + %1133 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1133 + %1137 = OpAccessChain %_ptr_Function_float %color %uint_1 + %1139 = OpLoad %int %1113 + OpStore %1113 %int_0 + OpStore %1113 %1139 + %1142 = OpCompositeExtract %float %949 1 + %1143 = OpCompositeExtract %float %938 0 + %1144 = OpCompositeConstruct %v2float %1142 %1143 + %1146 = OpLoad %float %1137 + OpStore %1137 %float_0 + OpStore %1137 %1146 + %1150 = OpLoad %float %1137 + %1152 = OpLoad %int %1113 + OpStore %1113 %int_0 + OpStore %1113 %1152 + %1155 = OpCompositeExtract %float %1121 0 + %1156 = OpCompositeExtract %float %929 0 + %1157 = OpCompositeConstruct %v2float %1155 %1156 + %1159 = OpLoad %float %985 + OpStore %985 %float_0 + OpStore %985 %1159 + %1162 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1162 + %1163 = OpCompositeExtract %float %1004 1 + %1164 = OpCompositeExtract %float %897 1 + %1165 = OpCompositeConstruct %v2float %1163 %1164 + %1166 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1166 + %1167 = OpAccessChain %_ptr_Function_float %color %uint_1 + %1168 = OpConvertSToF %float %1127 + %1169 = OpFAdd %float %1168 %1150 + OpStore %1167 %1169 + %1171 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1171 + OpBranch %1098 + %1098 = OpLabel + %1175 = OpAccessChain %_ptr_Function_float %uv %int_0 + %1176 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1176 + %1177 = OpCompositeExtract %float %938 0 + %1178 = OpCompositeExtract %float %938 0 + %1179 = OpCompositeConstruct %v2float %1177 %1178 + %1181 = OpLoad %float %1069 + OpStore %1069 %float_0 + OpStore %1069 %1181 + %1185 = OpLoad %float %1175 + %1186 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %1186 + %1188 = OpLoad %float %985 + OpStore %985 %float_0 + OpStore %985 %1188 + %1192 = OpFOrdGreaterThan %bool %1185 %float_0_75 + OpSelectionMerge %1193 None + OpBranchConditional %1192 %1194 %1193 + %1194 = OpLabel + %1196 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1196 + %1200 = OpAccessChain %_ptr_Private_int %obj %uint_0 %int_3 + %1201 = OpLoad %int %1200 + %1203 = OpLoad %float %985 + OpStore %985 %float_0 + OpStore %985 %1203 + %1206 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %1206 + %1207 = OpCompositeExtract %float %1179 0 + %1208 = OpCompositeExtract %float %1179 0 + %1209 = OpCompositeExtract %float %1179 0 + %1210 = OpCompositeConstruct %v3float %1207 %1208 %1209 + %1212 = OpLoad %float %1175 + OpStore %1175 %float_0 + OpStore %1175 %1212 + %1216 = OpAccessChain %_ptr_Function_float %color %uint_2 + %1218 = OpLoad %float %1069 + OpStore %1069 %float_0 + OpStore %1069 %1218 + %1222 = OpLoad %float %1216 + %1223 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %1223 + %1224 = OpCompositeExtract %float %1179 0 + %1225 = OpCompositeExtract %float %938 1 + %1226 = OpCompositeExtract %float %1179 1 + %1227 = OpCompositeConstruct %v3float %1224 %1225 %1226 + %1229 = OpLoad %float %1216 + OpStore %1216 %float_0 + OpStore %1216 %1229 + %1233 = OpLoad %int %959 + OpStore %959 %int_0 + OpStore %959 %1233 + %1236 = OpCompositeExtract %float %897 0 + %1237 = OpCompositeExtract %float %897 1 + %1238 = OpCompositeConstruct %v2float %1236 %1237 + %1240 = OpLoad %float %1216 + OpStore %1216 %float_0 + OpStore %1216 %1240 + %1243 = OpAccessChain %_ptr_Function_float %color %uint_2 + %1244 = OpConvertSToF %float %1201 + %1245 = OpFAdd %float %1222 %1244 + OpStore %1243 %1245 + %1246 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %1246 + %1247 = OpCompositeExtract %float %1238 1 + %1248 = OpCompositeExtract %float %1238 1 + %1249 = OpCompositeConstruct %v2float %1247 %1248 + OpBranch %1193 + %1193 = OpLabel + %1251 = OpLoad %float %1175 + OpStore %1175 %float_0 + OpStore %1175 %1251 + %1254 = OpCompositeExtract %float %999 0 + %1255 = OpCompositeExtract %float %999 1 + %1256 = OpCompositeExtract %float %999 1 + %1257 = OpCompositeConstruct %v3float %1254 %1255 %1256 + %1260 = OpAccessChain %_ptr_Private_int %obj %uint_0 %int_4 + %1262 = OpLoad %int %1260 + %1264 = OpLoad %float %1175 + OpStore %1175 %float_0 + OpStore %1175 %1264 + %1267 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %1267 + %1268 = OpCompositeExtract %float %917 1 + %1269 = OpCompositeExtract %float %989 0 + %1270 = OpCompositeExtract %float %989 0 + %1271 = OpCompositeConstruct %v3float %1268 %1269 %1270 + %1273 = OpLoad %int %1260 + OpStore %1260 %int_0 + OpStore %1260 %1273 + %1277 = OpAccessChain %_ptr_Function_float %color %uint_1 + %1278 = OpCompositeExtract %float %938 0 + %1279 = OpCompositeExtract %float %921 2 + %1280 = OpCompositeConstruct %v2float %1278 %1279 + %1282 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1282 + %1286 = OpLoad %float %1277 + %1288 = OpLoad %float %1277 + OpStore %1277 %float_0 + OpStore %1277 %1288 + %1291 = OpCompositeExtract %float %1179 0 + %1292 = OpCompositeExtract %float %949 0 + %1293 = OpCompositeConstruct %v2float %1291 %1292 + %1295 = OpLoad %float %1069 + OpStore %1069 %float_0 + OpStore %1069 %1295 + %1299 = OpAccessChain %_ptr_Function_float %color %uint_1 + %1301 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1301 + %1304 = OpCompositeExtract %float %956 2 + %1305 = OpCompositeExtract %float %1083 1 + %1306 = OpCompositeConstruct %v2float %1304 %1305 + %1308 = OpConvertSToF %float %1262 + %1309 = OpFAdd %float %1286 %1308 + OpStore %1299 %1309 + %1310 = OpCompositeExtract %float %897 0 + %1311 = OpCompositeExtract %float %1257 0 + %1312 = OpCompositeExtract %float %897 1 + %1313 = OpCompositeConstruct %v3float %1310 %1311 %1312 + %1315 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1315 + %1319 = OpAccessChain %_ptr_Function_float %uv %uint_1 + %1321 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1321 + %1324 = OpCompositeExtract %float %1257 0 + %1325 = OpCompositeExtract %float %1257 1 + %1326 = OpCompositeConstruct %v2float %1324 %1325 + %1328 = OpLoad %float %1319 + OpStore %1319 %float_0 + OpStore %1319 %1328 + %1332 = OpLoad %float %1319 + %1333 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1333 + %1334 = OpCompositeExtract %float %897 1 + %1335 = OpCompositeExtract %float %999 1 + %1336 = OpCompositeExtract %float %897 0 + %1337 = OpCompositeConstruct %v3float %1334 %1335 %1336 + %1339 = OpLoad %int %959 + OpStore %959 %int_0 + OpStore %959 %1339 + %1343 = OpLoad %float %1299 + OpStore %1299 %float_0 + OpStore %1299 %1343 + %1346 = OpCompositeExtract %float %917 0 + %1347 = OpCompositeExtract %float %917 0 + %1348 = OpCompositeExtract %float %897 1 + %1349 = OpCompositeConstruct %v3float %1346 %1347 %1348 + %1351 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1351 + %1354 = OpFOrdGreaterThan %bool %1332 %float_0_25 + OpSelectionMerge %1355 None + OpBranchConditional %1354 %1356 %1355 + %1356 = OpLabel + %1357 = OpCompositeExtract %float %925 0 + %1358 = OpCompositeExtract %float %1349 2 + %1359 = OpCompositeConstruct %v2float %1357 %1358 + %1360 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %1360 + %1362 = OpAccessChain %_ptr_Private_int %obj %uint_0 %uint_5 + %1363 = OpLoad %int %1362 + %1365 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1365 + %1368 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1368 + %1369 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1369 + %1370 = OpAccessChain %_ptr_Function_float %color %uint_0 + %1371 = OpLoad %float %1370 + %1373 = OpLoad %float %1175 + OpStore %1175 %float_0 + OpStore %1175 %1373 + %1376 = OpCompositeExtract %float %1004 0 + %1377 = OpCompositeExtract %float %1293 1 + %1378 = OpCompositeExtract %float %1004 1 + %1379 = OpCompositeConstruct %v3float %1376 %1377 %1378 + %1380 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %1380 + %1382 = OpLoad %float %1319 + OpStore %1319 %float_0 + OpStore %1319 %1382 + %1385 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1385 + %1386 = OpCompositeExtract %float %921 3 + %1387 = OpCompositeExtract %float %921 3 + %1388 = OpCompositeExtract %float %945 0 + %1389 = OpCompositeConstruct %v3float %1386 %1387 %1388 + %1391 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1391 + %1394 = OpAccessChain %_ptr_Function_float %color %uint_0 + %1395 = OpConvertSToF %float %1363 + %1396 = OpFAdd %float %1395 %1371 + OpStore %1394 %1396 + %1397 = OpCompositeExtract %float %999 1 + %1398 = OpCompositeExtract %float %949 0 + %1399 = OpCompositeExtract %float %999 1 + %1400 = OpCompositeConstruct %v3float %1397 %1398 %1399 + %1402 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1402 + OpBranch %1355 + %1355 = OpLabel + %1406 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1406 + %1409 = OpCompositeExtract %float %1179 0 + %1410 = OpCompositeExtract %float %949 1 + %1411 = OpCompositeExtract %float %949 0 + %1412 = OpCompositeConstruct %v3float %1409 %1410 %1411 + %1414 = OpLoad %float %1319 + OpStore %1319 %float_0 + OpStore %1319 %1414 + %1418 = OpAccessChain %_ptr_Function_float %uv %uint_1 + %1420 = OpLoad %int %1260 + OpStore %1260 %int_0 + OpStore %1260 %1420 + %1424 = OpLoad %float %1418 + %1426 = OpLoad %int %959 + OpStore %959 %int_0 + OpStore %959 %1426 + %1429 = OpFOrdGreaterThan %bool %1424 %float_0_5 + OpSelectionMerge %1430 None + OpBranchConditional %1429 %1431 %1430 + %1431 = OpLabel + %1433 = OpLoad %float %1069 + OpStore %1069 %float_0 + OpStore %1069 %1433 + %1436 = OpCompositeExtract %float %1349 1 + %1437 = OpCompositeExtract %float %1004 1 + %1438 = OpCompositeConstruct %v2float %1436 %1437 + %1441 = OpAccessChain %_ptr_Private_int %obj %uint_0 %uint_6 + %1443 = OpLoad %float %1277 + OpStore %1277 %float_0 + OpStore %1277 %1443 + %1446 = OpCompositeExtract %float %943 2 + %1447 = OpCompositeExtract %float %943 1 + %1448 = OpCompositeConstruct %v2float %1446 %1447 + %1450 = OpLoad %float %1418 + OpStore %1418 %float_0 + OpStore %1418 %1450 + %1454 = OpLoad %int %1441 + %1456 = OpLoad %float %1319 + OpStore %1319 %float_0 + OpStore %1319 %1456 + %1459 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1459 + %1461 = OpLoad %int %1260 + OpStore %1260 %int_0 + OpStore %1260 %1461 + %1464 = OpCompositeExtract %float %1271 2 + %1465 = OpCompositeExtract %float %1271 1 + %1466 = OpCompositeConstruct %v2float %1464 %1465 + %1467 = OpAccessChain %_ptr_Function_float %color %uint_1 + %1468 = OpLoad %float %1467 + %1469 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %1469 + %1471 = OpLoad %float %985 + OpStore %985 %float_0 + OpStore %985 %1471 + %1474 = OpCompositeExtract %float %1293 1 + %1475 = OpCompositeExtract %float %1293 0 + %1476 = OpCompositeConstruct %v2float %1474 %1475 + %1478 = OpLoad %int %1441 + OpStore %1441 %int_0 + OpStore %1441 %1478 + %1482 = OpLoad %int %1441 + OpStore %1441 %int_0 + OpStore %1441 %1482 + %1485 = OpCompositeExtract %float %1349 2 + %1486 = OpCompositeExtract %float %1349 2 + %1487 = OpCompositeConstruct %v2float %1485 %1486 + %1488 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %1488 + %1489 = OpAccessChain %_ptr_Function_float %color %uint_1 + %1490 = OpConvertSToF %float %1454 + %1491 = OpFAdd %float %1490 %1468 + OpStore %1489 %1491 + %1493 = OpLoad %float %985 + OpStore %985 %float_0 + OpStore %985 %1493 + %1496 = OpCompositeExtract %float %35 1 + %1497 = OpCompositeExtract %float %999 0 + %1498 = OpCompositeConstruct %v2float %1496 %1497 + %1500 = OpLoad %float %1299 + OpStore %1299 %float_0 + OpStore %1299 %1500 + OpBranch %1430 + %1430 = OpLabel + %1503 = OpCompositeExtract %float %1004 1 + %1504 = OpCompositeExtract %float %1004 1 + %1505 = OpCompositeConstruct %v2float %1503 %1504 + %1507 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1507 + %1511 = OpAccessChain %_ptr_Function_float %uv %uint_1 + %1513 = OpLoad %float %1511 + %1514 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %1514 + %1515 = OpCompositeExtract %float %1293 0 + %1516 = OpCompositeExtract %float %1293 1 + %1517 = OpCompositeConstruct %v2float %1515 %1516 + %1519 = OpLoad %float %1175 + OpStore %1175 %float_0 + OpStore %1175 %1519 + %1523 = OpLoad %float %1299 + OpStore %1299 %float_0 + OpStore %1299 %1523 + %1526 = OpCompositeExtract %float %938 0 + %1527 = OpCompositeExtract %float %938 1 + %1528 = OpCompositeExtract %float %938 1 + %1529 = OpCompositeConstruct %v3float %1526 %1527 %1528 + %1531 = OpLoad %int %1260 + OpStore %1260 %int_0 + OpStore %1260 %1531 + %1534 = OpFOrdGreaterThan %bool %1513 %float_0_75 + OpSelectionMerge %1535 None + OpBranchConditional %1534 %1536 %1535 + %1536 = OpLabel + %1537 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %1537 + %1539 = OpLoad %float %985 + OpStore %985 %float_0 + OpStore %985 %1539 + %1542 = OpCompositeExtract %float %945 1 + %1543 = OpCompositeExtract %float %945 0 + %1544 = OpCompositeExtract %float %945 1 + %1545 = OpCompositeConstruct %v3float %1542 %1543 %1544 + %1546 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %1546 + %1548 = OpAccessChain %_ptr_Private_int %obj %uint_0 %int_7 + %1549 = OpLoad %int %1548 + %1551 = OpLoad %float %1069 + OpStore %1069 %float_0 + OpStore %1069 %1551 + %1554 = OpCompositeExtract %float %1293 0 + %1555 = OpCompositeExtract %float %1179 1 + %1556 = OpCompositeExtract %float %1179 0 + %1557 = OpCompositeConstruct %v3float %1554 %1555 %1556 + %1559 = OpLoad %float %1299 + OpStore %1299 %float_0 + OpStore %1299 %1559 + %1562 = OpCompositeExtract %float %1313 0 + %1563 = OpCompositeExtract %float %1091 1 + %1564 = OpCompositeConstruct %v2float %1562 %1563 + %1566 = OpLoad %int %959 + OpStore %959 %int_0 + OpStore %959 %1566 + %1570 = OpLoad %float %1299 + OpStore %1299 %float_0 + OpStore %1299 %1570 + %1573 = OpCompositeExtract %float %1326 0 + %1574 = OpCompositeExtract %float %1326 1 + %1575 = OpCompositeExtract %float %1326 0 + %1576 = OpCompositeConstruct %v3float %1573 %1574 %1575 + %1578 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1578 + %1581 = OpAccessChain %_ptr_Function_float %color %uint_2 + %1582 = OpLoad %float %1581 + %1584 = OpLoad %float %1418 + OpStore %1418 %float_0 + OpStore %1418 %1584 + %1587 = OpCompositeExtract %float %921 0 + %1588 = OpCompositeExtract %float %921 1 + %1589 = OpCompositeConstruct %v2float %1587 %1588 + %1591 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1591 + %1595 = OpLoad %float %1511 + OpStore %1511 %float_0 + OpStore %1511 %1595 + %1599 = OpAccessChain %_ptr_Function_float %color %uint_2 + %1601 = OpLoad %float %1418 + OpStore %1418 %float_0 + OpStore %1418 %1601 + %1604 = OpCompositeExtract %float %1589 1 + %1605 = OpCompositeExtract %float %1589 1 + %1606 = OpCompositeExtract %float %1529 2 + %1607 = OpCompositeConstruct %v3float %1604 %1605 %1606 + %1609 = OpLoad %float %1599 + OpStore %1599 %float_0 + OpStore %1599 %1609 + %1613 = OpConvertSToF %float %1549 + %1614 = OpFAdd %float %1613 %1582 + OpStore %1599 %1614 + %1616 = OpLoad %float %1277 + OpStore %1277 %float_0 + OpStore %1277 %1616 + %1619 = OpCompositeExtract %float %989 0 + %1620 = OpCompositeExtract %float %989 2 + %1621 = OpCompositeConstruct %v2float %1619 %1620 + %1623 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1623 + OpBranch %1535 + %1535 = OpLabel + %1626 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1626 + %1627 = OpCompositeExtract %float %956 1 + %1628 = OpCompositeExtract %float %945 1 + %1629 = OpCompositeConstruct %v2float %1627 %1628 + %1630 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %1630 + %1633 = OpAccessChain %_ptr_Private_int %obj %uint_0 %int_8 + %1635 = OpLoad %int %1633 + %1636 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1636 + %1637 = OpCompositeExtract %float %929 0 + %1638 = OpCompositeExtract %float %956 2 + %1639 = OpCompositeConstruct %v2float %1637 %1638 + %1641 = OpLoad %int %1633 + OpStore %1633 %int_0 + OpStore %1633 %1641 + %1645 = OpLoad %float %1277 + OpStore %1277 %float_0 + OpStore %1277 %1645 + %1648 = OpCompositeExtract %float %989 1 + %1649 = OpCompositeExtract %float %897 0 + %1650 = OpCompositeConstruct %v2float %1648 %1649 + %1652 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1652 + %1656 = OpAccessChain %_ptr_Function_float %color %uint_2 + %1657 = OpCompositeExtract %float %1650 0 + %1658 = OpCompositeExtract %float %1650 1 + %1659 = OpCompositeExtract %float %1650 0 + %1660 = OpCompositeConstruct %v3float %1657 %1658 %1659 + %1662 = OpLoad %float %1656 + OpStore %1656 %float_0 + OpStore %1656 %1662 + %1666 = OpLoad %float %1656 + %1668 = OpLoad %float %985 + OpStore %985 %float_0 + OpStore %985 %1668 + %1671 = OpCompositeExtract %float %1517 0 + %1672 = OpCompositeExtract %float %1505 0 + %1673 = OpCompositeConstruct %v2float %1671 %1672 + %1675 = OpLoad %int %1260 + OpStore %1260 %int_0 + OpStore %1260 %1675 + %1679 = OpLoad %float %1511 + OpStore %1511 %float_0 + OpStore %1511 %1679 + %1682 = OpCompositeExtract %float %1091 0 + %1683 = OpCompositeExtract %float %925 0 + %1684 = OpCompositeConstruct %v2float %1682 %1683 + %1686 = OpLoad %float %1299 + OpStore %1299 %float_0 + OpStore %1299 %1686 + %1690 = OpAccessChain %_ptr_Function_float %color %uint_2 + %1692 = OpConvertSToF %float %1635 + %1693 = OpFAdd %float %1666 %1692 + OpStore %1690 %1693 + %1694 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %1694 + %1696 = OpLoad %float %1069 + OpStore %1069 %float_0 + OpStore %1069 %1696 + %1699 = OpCompositeExtract %float %1091 1 + %1700 = OpCompositeExtract %float %1091 0 + %1701 = OpCompositeExtract %float %1673 1 + %1702 = OpCompositeConstruct %v3float %1699 %1700 %1701 + %1704 = OpLoad %float %1069 + OpStore %1069 %float_0 + OpStore %1069 %1704 + %1707 = OpAccessChain %_ptr_Function_float %uv %uint_0 + %1708 = OpLoad %float %1707 + %1710 = OpLoad %float %1299 + OpStore %1299 %float_0 + OpStore %1299 %1710 + %1714 = OpAccessChain %_ptr_Function_float %uv %uint_1 + %1715 = OpCompositeExtract %float %1639 1 + %1716 = OpCompositeExtract %float %1639 0 + %1717 = OpCompositeExtract %float %933 2 + %1718 = OpCompositeConstruct %v3float %1715 %1716 %1717 + %1720 = OpLoad %float %1319 + OpStore %1319 %float_0 + OpStore %1319 %1720 + %1724 = OpLoad %float %1714 + %1726 = OpLoad %float %1319 + OpStore %1319 %float_0 + OpStore %1319 %1726 + %1730 = OpLoad %float %1690 + OpStore %1690 %float_0 + OpStore %1690 %1730 + %1733 = OpCompositeExtract %float %35 1 + %1734 = OpCompositeExtract %float %1412 1 + %1735 = OpCompositeExtract %float %1412 2 + %1736 = OpCompositeConstruct %v3float %1733 %1734 %1735 + %1738 = OpLoad %float %1690 + OpStore %1690 %float_0 + OpStore %1690 %1738 + %1741 = OpLoad %int %i_2 + OpStore %i_2 %int_0 + OpStore %i_2 %1741 + %1742 = OpCompositeExtract %float %1412 2 + %1743 = OpCompositeExtract %float %1412 1 + %1744 = OpCompositeConstruct %v2float %1742 %1743 + %1745 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %1745 + %1747 = OpLoad %float %1319 + OpStore %1319 %float_0 + OpStore %1319 %1747 + %1750 = OpCompositeExtract %float %1004 1 + %1751 = OpCompositeExtract %float %1004 1 + %1752 = OpCompositeExtract %float %1004 1 + %1753 = OpCompositeConstruct %v3float %1750 %1751 %1752 + %1755 = OpLoad %int %1260 + OpStore %1260 %int_0 + OpStore %1260 %1755 + %1760 = OpFSub %float %1708 %1724 + %1758 = OpExtInst %float %1759 FAbs %1760 + %1761 = OpFOrdLessThan %bool %1758 %float_0_25 + OpSelectionMerge %1762 None + OpBranchConditional %1761 %1763 %1762 + %1763 = OpLabel + %1765 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1765 + %1768 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %1768 + %1769 = OpCompositeExtract %float %1660 2 + %1770 = OpCompositeExtract %float %1660 0 + %1771 = OpCompositeExtract %float %933 0 + %1772 = OpCompositeConstruct %v3float %1769 %1770 %1771 + %1774 = OpLoad %int %1633 + OpStore %1633 %int_0 + OpStore %1633 %1774 + %1778 = OpAccessChain %_ptr_Private_int %obj %uint_0 %uint_9 + %1779 = OpLoad %int %1778 + %1780 = OpCompositeExtract %float %1280 1 + %1781 = OpCompositeExtract %float %1280 1 + %1782 = OpCompositeExtract %float %1280 1 + %1783 = OpCompositeConstruct %v3float %1780 %1781 %1782 + %1785 = OpLoad %float %1319 + OpStore %1319 %float_0 + OpStore %1319 %1785 + %1788 = OpAccessChain %_ptr_Function_float %color %uint_0 + %1789 = OpLoad %float %1788 + %1791 = OpLoad %float %1511 + OpStore %1511 %float_0 + OpStore %1511 %1791 + %1794 = OpCompositeExtract %float %1629 0 + %1795 = OpCompositeExtract %float %1629 1 + %1796 = OpCompositeConstruct %v2float %1794 %1795 + %1798 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1798 + %1801 = OpLoad %v3float %color + OpStore %color %909 + OpStore %color %1801 + %1802 = OpCompositeExtract %float %981 0 + %1803 = OpCompositeExtract %float %981 0 + %1804 = OpCompositeConstruct %v2float %1802 %1803 + %1805 = OpLoad %v2float %uv + OpStore %uv %897 + OpStore %uv %1805 + %1807 = OpAccessChain %_ptr_Function_float %color %uint_0 + %1809 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1809 + %1812 = OpCompositeExtract %float %897 0 + %1813 = OpCompositeExtract %float %897 0 + %1814 = OpCompositeExtract %float %897 1 + %1815 = OpCompositeConstruct %v3float %1812 %1813 %1814 + %1817 = OpConvertSToF %float %1779 + %1818 = OpFAdd %float %1817 %1789 + OpStore %1807 %1818 + %1820 = OpLoad %float %1807 + OpStore %1807 %float_0 + OpStore %1807 %1820 + %1823 = OpCompositeExtract %float %1349 1 + %1824 = OpCompositeExtract %float %1702 0 + %1825 = OpCompositeExtract %float %1349 0 + %1826 = OpCompositeConstruct %v3float %1823 %1824 %1825 + %1828 = OpLoad %float %968 + OpStore %968 %float_0 + OpStore %968 %1828 + OpBranch %1762 + %1762 = OpLabel + %1832 = OpLoad %float %1714 + OpStore %1714 %float_0 + OpStore %1714 %1832 + %1835 = OpLoad %v3float %color + %1837 = OpLoad %float %1175 + OpStore %1175 %float_0 + OpStore %1175 %1837 + %1840 = OpCompositeExtract %float %925 0 + %1841 = OpCompositeExtract %float %917 0 + %1842 = OpCompositeExtract %float %917 1 + %1843 = OpCompositeConstruct %v3float %1840 %1841 %1842 + %1844 = OpExtInst %v3float %1759 Normalize %1835 + %1846 = OpLoad %float %995 + OpStore %995 %float_0 + OpStore %995 %1846 + %1849 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %1849 + %1850 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %1850 + %1852 = OpLoad %float %1299 + OpStore %1299 %float_0 + OpStore %1299 %1852 + %1855 = OpCompositeExtract %float %1673 1 + %1856 = OpCompositeExtract %float %1843 1 + %1857 = OpCompositeConstruct %v2float %1855 %1856 + %1859 = OpLoad %float %1299 + OpStore %1299 %float_0 + OpStore %1299 %1859 + %1862 = OpCompositeExtract %float %1844 0 + %1863 = OpCompositeExtract %float %1844 1 + %1864 = OpCompositeExtract %float %1844 2 + %1865 = OpCompositeConstruct %v4float %1862 %1863 %1864 %float_1 + %1867 = OpLoad %float %1714 + OpStore %1714 %float_0 + OpStore %1714 %1867 + %1870 = OpCompositeExtract %float %35 1 + %1871 = OpCompositeExtract %float %35 1 + %1872 = OpCompositeExtract %float %1857 1 + %1873 = OpCompositeConstruct %v3float %1870 %1871 %1872 + %1875 = OpLoad %float %1069 + OpStore %1069 %float_0 + OpStore %1069 %1875 + OpStore %x_GLF_color %1865 + %1878 = OpLoad %QuicksortObject %obj + OpStore %obj %104 + OpStore %obj %1878 + %1879 = OpCompositeExtract %float %1865 3 + %1880 = OpCompositeExtract %float %1865 1 + %1881 = OpCompositeExtract %float %1517 0 + %1882 = OpCompositeConstruct %v3float %1879 %1880 %1881 + %1884 = OpLoad %float %985 + OpStore %985 %float_0 + OpStore %985 %1884 + OpReturn + OpFunctionEnd diff --git a/test/bug/tint/749.spvasm.expected.wgsl b/test/bug/tint/749.spvasm.expected.wgsl index 17ceb49b4c..48bb5b7910 100644 --- a/test/bug/tint/749.spvasm.expected.wgsl +++ b/test/bug/tint/749.spvasm.expected.wgsl @@ -21,84 +21,84 @@ fn swap_i1_i1_(i : ptr, j : ptr) { temp = 0; temp = x_932; let x_523 : vec3 = vec3(vec3(1.0, 2.0, 3.0).z, vec3(1.0, 2.0, 3.0).y, vec3(1.0, 2.0, 3.0).z); - let x_933 : i32 = i; - i = 0; - i = x_933; - let x_28 : i32 = i; - let x_934 : i32 = j; - j = 0; - j = x_934; + let x_933 : i32 = *(i); + *(i) = 0; + *(i) = x_933; + let x_28 : i32 = *(i); + let x_934 : i32 = *(j); + *(j) = 0; + *(j) = x_934; let x_524 : vec3 = vec3(x_523.y, x_523.x, x_523.y); let x_935 : i32 = temp; temp = 0; temp = x_935; - let x_30 : ptr = obj.numbers[x_28]; - let x_936 : i32 = x_30; - x_30 = 0; - x_30 = x_936; - let x_31 : i32 = x_30; + let x_30 : ptr = &(obj.numbers[x_28]); + let x_936 : i32 = *(x_30); + *(x_30) = 0; + *(x_30) = x_936; + let x_31 : i32 = *(x_30); let x_937 : i32 = temp; temp = 0; temp = x_937; temp = x_31; - let x_938 : i32 = j; - j = 0; - j = x_938; + let x_938 : i32 = *(j); + *(j) = 0; + *(j) = x_938; let x_525 : vec3 = vec3(x_523.z, vec3(1.0, 2.0, 3.0).x, x_523.y); - let x_939 : i32 = i; - i = 0; - i = x_939; - let x_32 : i32 = i; - let x_940 : i32 = x_30; - x_30 = 0; - x_30 = x_940; - let x_33 : i32 = j; - let x_941 : i32 = i; - i = 0; - i = x_941; + let x_939 : i32 = *(i); + *(i) = 0; + *(i) = x_939; + let x_32 : i32 = *(i); + let x_940 : i32 = *(x_30); + *(x_30) = 0; + *(x_30) = x_940; + let x_33 : i32 = *(j); + let x_941 : i32 = *(i); + *(i) = 0; + *(i) = x_941; let x_526 : vec3 = vec3(x_525.x, x_525.z, x_525.z); - let x_942 : i32 = x_30; - x_30 = 0; - x_30 = x_942; - let x_34 : ptr = obj.numbers[x_33]; - let x_35 : i32 = x_34; + let x_942 : i32 = *(x_30); + *(x_30) = 0; + *(x_30) = x_942; + let x_34 : ptr = &(obj.numbers[x_33]); + let x_35 : i32 = *(x_34); let x_943 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_943; let x_527 : vec2 = vec2(x_526.x, x_526.x); - let x_36 : ptr = obj.numbers[x_32]; + let x_36 : ptr = &(obj.numbers[x_32]); let x_528 : vec3 = vec3(x_524.x, x_524.z, x_524.x); - x_36 = x_35; + *(x_36) = x_35; let x_944 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_944; let x_529 : vec3 = vec3(x_526.y, x_526.z, x_526.x); - let x_945 : i32 = i; - i = 0; - i = x_945; - let x_37 : i32 = j; + let x_945 : i32 = *(i); + *(i) = 0; + *(i) = x_945; + let x_37 : i32 = *(j); let x_946 : i32 = temp; temp = 0; temp = x_946; let x_530 : vec2 = vec2(x_529.z, x_529.y); - let x_947 : i32 = x_34; - x_34 = 0; - x_34 = x_947; + let x_947 : i32 = *(x_34); + *(x_34) = 0; + *(x_34) = x_947; let x_38 : i32 = temp; - let x_948 : i32 = j; - j = 0; - j = x_948; + let x_948 : i32 = *(j); + *(j) = 0; + *(j) = x_948; let x_531 : vec3 = vec3(x_527.x, x_526.y, x_526.x); - let x_949 : i32 = x_36; - x_36 = 0; - x_36 = x_949; + let x_949 : i32 = *(x_36); + *(x_36) = 0; + *(x_36) = x_949; let x_950 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_950; let x_532 : vec3 = vec3(x_528.x, x_528.y, x_528.x); - let x_951 : i32 = x_34; - x_34 = 0; - x_34 = x_951; + let x_951 : i32 = *(x_34); + *(x_34) = 0; + *(x_34) = x_951; obj.numbers[x_37] = x_38; return; } @@ -113,18 +113,18 @@ fn performPartition_i1_i1_(l : ptr, h : ptr) -> i3 var pivot : i32; var x_537 : vec2; var x_538 : vec3; - let x_952 : i32 = h; - h = 0; - h = x_952; - let x_41 : i32 = h; - let x_953 : i32 = l; - l = 0; - l = x_953; - let x_42 : ptr = obj.numbers[x_41]; - let x_954 : i32 = x_42; - x_42 = 0; - x_42 = x_954; - let x_43 : i32 = x_42; + let x_952 : i32 = *(h); + *(h) = 0; + *(h) = x_952; + let x_41 : i32 = *(h); + let x_953 : i32 = *(l); + *(l) = 0; + *(l) = x_953; + let x_42 : ptr = &(obj.numbers[x_41]); + let x_954 : i32 = *(x_42); + *(x_42) = 0; + *(x_42) = x_954; + let x_43 : i32 = *(x_42); let x_955 : i32 = param_3; param_3 = 0; param_3 = x_955; @@ -133,19 +133,19 @@ fn performPartition_i1_i1_(l : ptr, h : ptr) -> i3 param_1 = 0; param_1 = x_956; pivot = x_43; - let x_45 : i32 = l; - let x_957 : i32 = h; - h = 0; - h = x_957; + let x_45 : i32 = *(l); + let x_957 : i32 = *(h); + *(h) = 0; + *(h) = x_957; let x_958 : i32 = j_1; j_1 = 0; j_1 = x_958; let x_535 : vec3 = vec3(x_534.y, x_534.z, x_534.y); - let x_959 : i32 = l; - l = 0; - l = x_959; + let x_959 : i32 = *(l); + *(l) = 0; + *(l) = x_959; i_1 = (x_45 - bitcast(1u)); - let x_49 : i32 = l; + let x_49 : i32 = *(l); let x_536 : vec3 = vec3(x_534.x, x_534.z, x_535.x); j_1 = 10; let x_960 : QuicksortObject = obj; @@ -166,10 +166,10 @@ fn performPartition_i1_i1_(l : ptr, h : ptr) -> i3 let x_964 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_964; - let x_56 : i32 = h; - let x_965 : i32 = h; - h = 0; - h = x_965; + let x_56 : i32 = *(h); + let x_965 : i32 = *(h); + *(h) = 0; + *(h) = x_965; let x_966 : i32 = param; param = 0; param = x_966; @@ -185,18 +185,18 @@ fn performPartition_i1_i1_(l : ptr, h : ptr) -> i3 break; } let x_60 : i32 = j_1; - let x_969 : i32 = x_42; - x_42 = 0; - x_42 = x_969; - let x_61 : ptr = obj.numbers[x_60]; - let x_970 : i32 = h; - h = 0; - h = x_970; + let x_969 : i32 = *(x_42); + *(x_42) = 0; + *(x_42) = x_969; + let x_61 : ptr = &(obj.numbers[x_60]); + let x_970 : i32 = *(h); + *(h) = 0; + *(h) = x_970; let x_539 : vec3 = vec3(x_537.x, x_535.z, x_537.x); let x_971 : i32 = param_1; param_1 = 0; param_1 = x_971; - let x_62 : i32 = x_61; + let x_62 : i32 = *(x_61); let x_972 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_972; @@ -205,9 +205,9 @@ fn performPartition_i1_i1_(l : ptr, h : ptr) -> i3 let x_973 : i32 = i_1; i_1 = 0; i_1 = x_973; - let x_974 : i32 = l; - l = 0; - l = x_974; + let x_974 : i32 = *(l); + *(l) = 0; + *(l) = x_974; let x_541 : vec3 = vec3(x_534.y, x_534.x, x_534.y); let x_975 : i32 = pivot; pivot = 0; @@ -229,9 +229,9 @@ fn performPartition_i1_i1_(l : ptr, h : ptr) -> i3 param = 0; param = x_979; i_1 = (x_67 + bitcast(1u)); - let x_980 : i32 = l; - l = 0; - l = x_980; + let x_980 : i32 = *(l); + *(l) = 0; + *(l) = x_980; let x_544 : vec3 = vec3(vec3(1.0, 2.0, 3.0).z, vec3(1.0, 2.0, 3.0).y, x_540.x); let x_70 : i32 = i_1; let x_545 : vec2 = vec2(x_537.y, x_538.x); @@ -251,7 +251,7 @@ fn performPartition_i1_i1_(l : ptr, h : ptr) -> i3 let x_984 : i32 = param_3; param_3 = 0; param_3 = x_984; - swap_i1_i1_(param, param_1); + swap_i1_i1_(&(param), &(param_1)); let x_985 : i32 = param_1; param_1 = 0; param_1 = x_985; @@ -261,17 +261,17 @@ fn performPartition_i1_i1_(l : ptr, h : ptr) -> i3 obj = x_986; continuing { - let x_987 : i32 = h; - h = 0; - h = x_987; + let x_987 : i32 = *(h); + *(h) = 0; + *(h) = x_987; let x_74 : i32 = j_1; - let x_988 : i32 = h; - h = 0; - h = x_988; + let x_988 : i32 = *(h); + *(h) = 0; + *(h) = x_988; let x_547 : vec3 = vec3(x_539.x, x_541.z, x_541.z); - let x_989 : i32 = x_61; - x_61 = 0; - x_61 = x_989; + let x_989 : i32 = *(x_61); + *(x_61) = 0; + *(x_61) = x_989; let x_990 : i32 = param; param = 0; param = x_990; @@ -280,22 +280,22 @@ fn performPartition_i1_i1_(l : ptr, h : ptr) -> i3 param_1 = 0; param_1 = x_991; let x_548 : vec3 = vec3(x_541.y, x_541.z, x_541.x); - let x_992 : i32 = x_61; - x_61 = 0; - x_61 = x_992; + let x_992 : i32 = *(x_61); + *(x_61) = 0; + *(x_61) = x_992; } } let x_76 : i32 = i_1; - let x_993 : i32 = x_42; - x_42 = 0; - x_42 = x_993; + let x_993 : i32 = *(x_42); + *(x_42) = 0; + *(x_42) = x_993; let x_549 : vec2 = vec2(x_534.x, x_534.y); let x_994 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_994; - let x_995 : i32 = h; - h = 0; - h = x_995; + let x_995 : i32 = *(h); + *(h) = 0; + *(h) = x_995; i_1 = (1 + x_76); let x_996 : i32 = param_1; param_1 = 0; @@ -313,23 +313,23 @@ fn performPartition_i1_i1_(l : ptr, h : ptr) -> i3 let x_999 : i32 = pivot; pivot = 0; pivot = x_999; - let x_81 : i32 = h; + let x_81 : i32 = *(h); let x_552 : vec2 = vec2(x_550.x, x_549.y); - let x_1000 : i32 = h; - h = 0; - h = x_1000; + let x_1000 : i32 = *(h); + *(h) = 0; + *(h) = x_1000; param_3 = x_81; let x_1001 : i32 = i_1; i_1 = 0; i_1 = x_1001; let x_553 : vec2 = vec2(x_549.y, x_552.x); - let x_1002 : i32 = h; - h = 0; - h = x_1002; - swap_i1_i1_(param_2, param_3); - let x_1003 : i32 = l; - l = 0; - l = x_1003; + let x_1002 : i32 = *(h); + *(h) = 0; + *(h) = x_1002; + swap_i1_i1_(&(param_2), &(param_3)); + let x_1003 : i32 = *(l); + *(l) = 0; + *(l) = x_1003; let x_554 : vec2 = vec2(x_536.z, vec3(1.0, 2.0, 3.0).y); let x_1004 : i32 = param_1; param_1 = 0; @@ -395,7 +395,7 @@ fn quicksort_() { obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_1016; let x_560 : vec3 = vec3(x_559.y, x_559.x, x_557.x); - let x_96 : ptr = stack[x_94]; + let x_96 : ptr = &(stack[x_94]); let x_1017 : array = stack; stack = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); stack = x_1017; @@ -403,7 +403,7 @@ fn quicksort_() { let x_1018 : i32 = l_1; l_1 = 0; l_1 = 0; - x_96 = x_95; + *(x_96) = x_95; let x_1019 : i32 = param_5; param_5 = 0; param_5 = x_1019; @@ -412,13 +412,13 @@ fn quicksort_() { param_4 = 0; param_4 = x_1020; let x_562 : vec3 = vec3(vec3(1.0, 2.0, 3.0).z, x_558.y, vec3(1.0, 2.0, 3.0).y); - let x_1021 : i32 = x_96; - x_96 = 0; - x_96 = x_1021; + let x_1021 : i32 = *(x_96); + *(x_96) = 0; + *(x_96) = x_1021; let x_98 : i32 = (x_97 + 1); - let x_1022 : i32 = x_96; - x_96 = 0; - x_96 = x_1022; + let x_1022 : i32 = *(x_96); + *(x_96) = 0; + *(x_96) = x_1022; let x_563 : vec3 = vec3(x_559.x, x_559.z, x_556.y); top = x_98; let x_1023 : i32 = param_4; @@ -432,7 +432,7 @@ fn quicksort_() { let x_1025 : i32 = l_1; l_1 = 0; l_1 = x_1025; - let x_100 : ptr = stack[x_98]; + let x_100 : ptr = &(stack[x_98]); let x_1026 : i32 = param_5; param_5 = 0; param_5 = x_1026; @@ -440,7 +440,7 @@ fn quicksort_() { let x_1027 : i32 = p; p = 0; p = x_1027; - x_100 = x_99; + *(x_100) = x_99; loop { let x_566 : vec3 = vec3(x_563.x, x_563.x, x_563.x); let x_1028 : i32 = h_1; @@ -481,11 +481,11 @@ fn quicksort_() { let x_1036 : i32 = p; p = 0; p = x_1036; - let x_110 : ptr = stack[x_108]; - let x_1037 : i32 = x_96; - x_96 = 0; - x_96 = x_1037; - let x_111 : i32 = x_110; + let x_110 : ptr = &(stack[x_108]); + let x_1037 : i32 = *(x_96); + *(x_96) = 0; + *(x_96) = x_1037; + let x_111 : i32 = *(x_110); let x_1038 : array = stack; stack = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); stack = x_1038; @@ -505,9 +505,9 @@ fn quicksort_() { let x_1042 : i32 = param_4; param_4 = 0; param_4 = x_1042; - let x_1043 : i32 = x_100; - x_100 = 0; - x_100 = x_1043; + let x_1043 : i32 = *(x_100); + *(x_100) = 0; + *(x_100) = x_1043; let x_573 : vec2 = vec2(vec3(1.0, 2.0, 3.0).y, vec3(1.0, 2.0, 3.0).z); top = (x_112 - 1); let x_1044 : i32 = param_5; @@ -517,12 +517,12 @@ fn quicksort_() { let x_1045 : i32 = h_1; h_1 = 0; h_1 = x_1045; - let x_114 : ptr = stack[x_112]; + let x_114 : ptr = &(stack[x_112]); let x_575 : vec2 = vec2(x_564.y, x_564.z); - let x_1046 : i32 = x_100; - x_100 = 0; - x_100 = x_1046; - let x_115 : i32 = x_114; + let x_1046 : i32 = *(x_100); + *(x_100) = 0; + *(x_100) = x_1046; + let x_115 : i32 = *(x_114); let x_1047 : i32 = p; p = 0; p = x_1047; @@ -536,17 +536,17 @@ fn quicksort_() { top = x_1049; let x_118 : i32 = l_1; param_4 = x_118; - let x_1050 : i32 = x_110; - x_110 = 0; - x_110 = x_1050; + let x_1050 : i32 = *(x_110); + *(x_110) = 0; + *(x_110) = x_1050; let x_577 : vec2 = vec2(x_569.y, x_569.z); let x_120 : i32 = h_1; let x_578 : vec2 = vec2(x_558.x, vec3(1.0, 2.0, 3.0).y); param_5 = x_120; - let x_1051 : i32 = x_100; - x_100 = 0; - x_100 = x_1051; - let x_121 : i32 = performPartition_i1_i1_(param_4, param_5); + let x_1051 : i32 = *(x_100); + *(x_100) = 0; + *(x_100) = x_1051; + let x_121 : i32 = performPartition_i1_i1_(&(param_4), &(param_5)); let x_579 : vec2 = vec2(x_567.x, x_568.x); let x_1052 : i32 = param_5; param_5 = 0; @@ -567,59 +567,59 @@ fn quicksort_() { h_1 = 0; h_1 = x_1056; let x_124 : i32 = l_1; - let x_1057 : i32 = x_110; - x_110 = 0; - x_110 = x_1057; + let x_1057 : i32 = *(x_110); + *(x_110) = 0; + *(x_110) = x_1057; let x_1058 : i32 = h_1; h_1 = 0; h_1 = x_1058; let x_582 : vec2 = vec2(x_567.y, x_573.x); - let x_1059 : i32 = x_100; - x_100 = 0; - x_100 = x_1059; + let x_1059 : i32 = *(x_100); + *(x_100) = 0; + *(x_100) = x_1059; if (((x_122 - bitcast(1u)) > x_124)) { let x_1060 : i32 = param_4; param_4 = 0; param_4 = x_1060; let x_128 : i32 = top; let x_583 : vec2 = vec2(x_571.y, x_556.y); - let x_1061 : i32 = x_100; - x_100 = 0; - x_100 = x_1061; + let x_1061 : i32 = *(x_100); + *(x_100) = 0; + *(x_100) = x_1061; let x_1062 : array = stack; stack = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); stack = x_1062; let x_584 : vec2 = vec2(x_569.z, x_569.y); let x_585 : vec3 = vec3(x_580.y, x_577.x, x_577.x); let x_130 : i32 = l_1; - let x_1063 : i32 = x_114; - x_114 = 0; - x_114 = x_1063; + let x_1063 : i32 = *(x_114); + *(x_114) = 0; + *(x_114) = x_1063; let x_586 : vec2 = vec2(x_564.x, x_585.x); let x_1064 : i32 = param_5; param_5 = 0; param_5 = x_1064; - let x_131 : ptr = stack[(1 + x_128)]; - let x_1065 : i32 = x_110; - x_110 = 0; - x_110 = x_1065; + let x_131 : ptr = &(stack[(1 + x_128)]); + let x_1065 : i32 = *(x_110); + *(x_110) = 0; + *(x_110) = x_1065; let x_587 : vec3 = vec3(x_566.y, x_566.y, x_563.x); let x_1066 : i32 = param_5; param_5 = 0; param_5 = x_1066; - x_131 = x_130; + *(x_131) = x_130; let x_132 : i32 = top; - let x_1067 : i32 = x_100; - x_100 = 0; - x_100 = x_1067; + let x_1067 : i32 = *(x_100); + *(x_100) = 0; + *(x_100) = x_1067; let x_588 : vec2 = vec2(x_575.y, x_575.x); - let x_1068 : i32 = x_131; - x_131 = 0; - x_131 = x_1068; + let x_1068 : i32 = *(x_131); + *(x_131) = 0; + *(x_131) = x_1068; let x_133 : i32 = bitcast((1u + bitcast(x_132))); - let x_1069 : i32 = x_100; - x_100 = 0; - x_100 = x_1069; + let x_1069 : i32 = *(x_100); + *(x_100) = 0; + *(x_100) = x_1069; let x_589 : vec3 = vec3(x_576.z, x_588.y, x_576.z); let x_1070 : i32 = h_1; h_1 = 0; @@ -630,73 +630,73 @@ fn quicksort_() { stack = x_1071; let x_134 : i32 = p; let x_590 : vec2 = vec2(x_576.x, x_573.y); - let x_1072 : i32 = x_114; - x_114 = 0; - x_114 = x_1072; - let x_136 : ptr = stack[x_133]; - let x_1073 : i32 = x_114; - x_114 = 0; - x_114 = x_1073; - x_136 = (x_134 - bitcast(1u)); - let x_1074 : i32 = x_96; - x_96 = 0; - x_96 = x_1074; + let x_1072 : i32 = *(x_114); + *(x_114) = 0; + *(x_114) = x_1072; + let x_136 : ptr = &(stack[x_133]); + let x_1073 : i32 = *(x_114); + *(x_114) = 0; + *(x_114) = x_1073; + *(x_136) = (x_134 - bitcast(1u)); + let x_1074 : i32 = *(x_96); + *(x_96) = 0; + *(x_96) = x_1074; let x_591 : vec2 = vec2(x_569.z, x_569.y); - let x_1075 : i32 = x_136; - x_136 = 0; - x_136 = x_1075; + let x_1075 : i32 = *(x_136); + *(x_136) = 0; + *(x_136) = x_1075; } - let x_1076 : i32 = x_96; - x_96 = 0; - x_96 = x_1076; + let x_1076 : i32 = *(x_96); + *(x_96) = 0; + *(x_96) = x_1076; let x_592 : vec2 = vec2(vec3(1.0, 2.0, 3.0).x, vec3(1.0, 2.0, 3.0).y); let x_1077 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_1077; let x_137 : i32 = p; - let x_1078 : i32 = x_114; - x_114 = 0; - x_114 = x_1078; + let x_1078 : i32 = *(x_114); + *(x_114) = 0; + *(x_114) = x_1078; let x_593 : vec3 = vec3(x_571.z, x_556.x, x_556.y); let x_1079 : i32 = p; p = 0; p = x_1079; let x_594 : vec3 = vec3(x_563.z, x_563.x, x_575.x); - let x_1080 : i32 = x_114; - x_114 = 0; - x_114 = x_1080; + let x_1080 : i32 = *(x_114); + *(x_114) = 0; + *(x_114) = x_1080; let x_139 : i32 = h_1; let x_1081 : i32 = top; top = 0; top = x_1081; let x_595 : vec3 = vec3(x_560.z, x_568.x, x_560.x); - let x_1082 : i32 = x_100; - x_100 = 0; - x_100 = x_1082; + let x_1082 : i32 = *(x_100); + *(x_100) = 0; + *(x_100) = x_1082; let x_1083 : i32 = p; p = 0; p = x_1083; if ((bitcast((1u + bitcast(x_137))) < x_139)) { - let x_1084 : i32 = x_114; - x_114 = 0; - x_114 = x_1084; + let x_1084 : i32 = *(x_114); + *(x_114) = 0; + *(x_114) = x_1084; let x_596 : vec2 = vec2(x_592.y, x_582.x); let x_1085 : i32 = l_1; l_1 = 0; l_1 = x_1085; let x_143 : i32 = top; - let x_1086 : i32 = x_114; - x_114 = 0; - x_114 = x_1086; + let x_1086 : i32 = *(x_114); + *(x_114) = 0; + *(x_114) = x_1086; let x_597 : vec3 = vec3(x_562.y, x_560.y, x_560.y); let x_144 : i32 = (x_143 + 1); let x_1087 : i32 = param_5; param_5 = 0; param_5 = x_1087; top = x_144; - let x_1088 : i32 = x_114; - x_114 = 0; - x_114 = x_1088; + let x_1088 : i32 = *(x_114); + *(x_114) = 0; + *(x_114) = x_1088; let x_145 : i32 = p; let x_1089 : i32 = param_5; param_5 = 0; @@ -706,53 +706,53 @@ fn quicksort_() { p = 0; p = x_1090; let x_600 : vec3 = vec3(x_556.x, x_580.x, x_580.x); - let x_1091 : i32 = x_100; - x_100 = 0; - x_100 = x_1091; - let x_147 : ptr = stack[x_144]; - let x_1092 : i32 = x_110; - x_110 = 0; - x_110 = x_1092; + let x_1091 : i32 = *(x_100); + *(x_100) = 0; + *(x_100) = x_1091; + let x_147 : ptr = &(stack[x_144]); + let x_1092 : i32 = *(x_110); + *(x_110) = 0; + *(x_110) = x_1092; let x_601 : vec2 = vec2(x_563.x, x_563.y); - x_147 = bitcast((1u + bitcast(x_145))); + *(x_147) = bitcast((1u + bitcast(x_145))); let x_1093 : array = stack; stack = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); stack = x_1093; let x_148 : i32 = top; - let x_1094 : i32 = x_114; - x_114 = 0; - x_114 = x_1094; + let x_1094 : i32 = *(x_114); + *(x_114) = 0; + *(x_114) = x_1094; let x_602 : vec2 = vec2(x_565.y, x_599.y); let x_1095 : array = stack; stack = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); stack = x_1095; let x_149 : i32 = (x_148 + bitcast(1u)); - let x_1096 : i32 = x_147; - x_147 = 0; - x_147 = x_1096; + let x_1096 : i32 = *(x_147); + *(x_147) = 0; + *(x_147) = x_1096; top = x_149; let x_1097 : i32 = param_4; param_4 = 0; param_4 = x_1097; let x_150 : i32 = h_1; - let x_1098 : i32 = x_100; - x_100 = 0; - x_100 = x_1098; - let x_1099 : i32 = x_96; - x_96 = 0; - x_96 = x_1099; + let x_1098 : i32 = *(x_100); + *(x_100) = 0; + *(x_100) = x_1098; + let x_1099 : i32 = *(x_96); + *(x_96) = 0; + *(x_96) = x_1099; stack[x_149] = x_150; - let x_1100 : i32 = x_114; - x_114 = 0; - x_114 = x_1100; + let x_1100 : i32 = *(x_114); + *(x_114) = 0; + *(x_114) = x_1100; let x_603 : vec3 = vec3(x_568.y, x_564.x, x_564.x); let x_1101 : i32 = l_1; l_1 = 0; l_1 = x_1101; } - let x_1102 : i32 = x_100; - x_100 = 0; - x_100 = x_1102; + let x_1102 : i32 = *(x_100); + *(x_100) = 0; + *(x_100) = x_1102; continuing { let x_1103 : i32 = l_1; @@ -854,22 +854,22 @@ fn main() { let x_769 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_769; - let x_200 : ptr = obj.numbers[0u]; - let x_770 : i32 = x_200; - x_200 = 0; - x_200 = x_770; - let x_201 : i32 = x_200; + let x_200 : ptr = &(obj.numbers[0u]); + let x_770 : i32 = *(x_200); + *(x_200) = 0; + *(x_200) = x_770; + let x_201 : i32 = *(x_200); let x_771 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_771; - let x_205 : ptr = color.x; - let x_772 : i32 = x_200; - x_200 = 0; - x_200 = x_772; - let x_206 : f32 = x_205; - let x_773 : f32 = x_205; - x_205 = 0.0; - x_205 = x_773; + let x_205 : ptr = &(color.x); + let x_772 : i32 = *(x_200); + *(x_200) = 0; + *(x_200) = x_772; + let x_206 : f32 = *(x_205); + let x_773 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_773; let x_452 : vec2 = vec2(vec3(1.0, 2.0, 3.0).z, vec3(1.0, 2.0, 3.0).y); let x_774 : i32 = i_2; i_2 = 0; @@ -877,22 +877,22 @@ fn main() { let x_775 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_775; - let x_208 : ptr = color.x; + let x_208 : ptr = &(color.x); let x_453 : vec3 = vec3(x_451.x, x_450.x, x_450.y); - x_208 = (x_206 + f32(x_201)); + *(x_208) = (x_206 + f32(x_201)); let x_776 : vec2 = uv; uv = vec2(0.0, 0.0); uv = x_776; - let x_209 : ptr = uv.x; + let x_209 : ptr = &(uv.x); let x_777 : vec2 = uv; uv = vec2(0.0, 0.0); uv = x_777; let x_454 : vec2 = vec2(x_184.y, x_184.y); - let x_210 : f32 = x_209; + let x_210 : f32 = *(x_209); let x_455 : vec2 = vec2(x_192.y, x_192.x); - let x_778 : f32 = x_209; - x_209 = 0.0; - x_209 = x_778; + let x_778 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_778; let x_779 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_779; @@ -900,13 +900,13 @@ fn main() { let x_780 : i32 = i_2; i_2 = 0; i_2 = x_780; - let x_781 : i32 = x_200; - x_200 = 0; - x_200 = x_781; + let x_781 : i32 = *(x_200); + *(x_200) = 0; + *(x_200) = x_781; let x_456 : vec3 = vec3(vec2(0.0, 0.0).y, x_448.y, x_448.y); - let x_782 : f32 = x_209; - x_209 = 0.0; - x_209 = x_782; + let x_782 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_782; let x_216 : i32 = obj.numbers[1]; let x_783 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); @@ -915,7 +915,7 @@ fn main() { let x_784 : vec2 = uv; uv = vec2(0.0, 0.0); uv = x_784; - let x_218 : ptr = color[0]; + let x_218 : ptr = &(color[0]); let x_785 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_785; @@ -923,10 +923,10 @@ fn main() { let x_786 : i32 = i_2; i_2 = 0; i_2 = x_786; - let x_219 : f32 = x_218; - let x_787 : f32 = x_218; - x_218 = 0.0; - x_218 = x_787; + let x_219 : f32 = *(x_218); + let x_787 : f32 = *(x_218); + *(x_218) = 0.0; + *(x_218) = x_787; let x_788 : vec3 = color; color = vec3(0.0, 0.0, 0.0); color = x_788; @@ -934,75 +934,75 @@ fn main() { color = vec3(0.0, 0.0, 0.0); color = x_789; let x_459 : vec3 = vec3(x_454.y, x_454.y, x_447.y); - let x_790 : f32 = x_218; - x_218 = 0.0; - x_218 = x_790; + let x_790 : f32 = *(x_218); + *(x_218) = 0.0; + *(x_218) = x_790; color.x = (f32(x_216) + x_219); - let x_791 : i32 = x_200; - x_200 = 0; - x_200 = x_791; + let x_791 : i32 = *(x_200); + *(x_200) = 0; + *(x_200) = x_791; } - let x_792 : f32 = x_209; - x_209 = 0.0; - x_209 = x_792; - let x_222 : ptr = uv.x; - let x_793 : f32 = x_209; - x_209 = 0.0; - x_209 = x_793; - let x_223 : f32 = x_222; - let x_794 : f32 = x_222; - x_222 = 0.0; - x_222 = x_794; + let x_792 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_792; + let x_222 : ptr = &(uv.x); + let x_793 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_793; + let x_223 : f32 = *(x_222); + let x_794 : f32 = *(x_222); + *(x_222) = 0.0; + *(x_222) = x_794; let x_460 : vec3 = vec3(x_453.z, x_453.y, x_453.y); let x_795 : vec2 = uv; uv = vec2(0.0, 0.0); uv = x_795; - let x_796 : f32 = x_222; - x_222 = 0.0; - x_222 = x_796; + let x_796 : f32 = *(x_222); + *(x_222) = 0.0; + *(x_222) = x_796; let x_461 : vec2 = vec2(vec2(0.0, 0.0).y, vec2(0.0, 0.0).y); - let x_797 : f32 = x_222; - x_222 = 0.0; - x_222 = x_797; + let x_797 : f32 = *(x_222); + *(x_222) = 0.0; + *(x_222) = x_797; if ((x_223 > 0.5)) { - let x_798 : f32 = x_222; - x_222 = 0.0; - x_222 = x_798; + let x_798 : f32 = *(x_222); + *(x_222) = 0.0; + *(x_222) = x_798; let x_462 : vec2 = vec2(x_446.x, x_446.x); - let x_799 : f32 = x_205; - x_205 = 0.0; - x_205 = x_799; - let x_229 : ptr = obj.numbers[2u]; - let x_800 : f32 = x_205; - x_205 = 0.0; - x_205 = x_800; + let x_799 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_799; + let x_229 : ptr = &(obj.numbers[2u]); + let x_800 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_800; let x_463 : vec3 = vec3(x_453.x, x_453.z, x_461.y); - let x_801 : f32 = x_208; - x_208 = 0.0; - x_208 = x_801; - let x_230 : i32 = x_229; - let x_802 : f32 = x_209; - x_209 = 0.0; - x_209 = x_802; - let x_803 : f32 = x_205; - x_205 = 0.0; - x_205 = x_803; - let x_233 : ptr = color.y; - let x_804 : i32 = x_229; - x_229 = 0; - x_229 = x_804; + let x_801 : f32 = *(x_208); + *(x_208) = 0.0; + *(x_208) = x_801; + let x_230 : i32 = *(x_229); + let x_802 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_802; + let x_803 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_803; + let x_233 : ptr = &(color.y); + let x_804 : i32 = *(x_229); + *(x_229) = 0; + *(x_229) = x_804; let x_464 : vec2 = vec2(x_450.y, x_191.x); - let x_805 : f32 = x_233; - x_233 = 0.0; - x_233 = x_805; - let x_234 : f32 = x_233; - let x_806 : i32 = x_229; - x_229 = 0; - x_229 = x_806; + let x_805 : f32 = *(x_233); + *(x_233) = 0.0; + *(x_233) = x_805; + let x_234 : f32 = *(x_233); + let x_806 : i32 = *(x_229); + *(x_229) = 0; + *(x_229) = x_806; let x_465 : vec2 = vec2(x_463.x, x_185.x); - let x_807 : f32 = x_208; - x_208 = 0.0; - x_208 = x_807; + let x_807 : f32 = *(x_208); + *(x_208) = 0.0; + *(x_208) = x_807; let x_808 : i32 = i_2; i_2 = 0; i_2 = x_808; @@ -1011,136 +1011,136 @@ fn main() { i_2 = 0; i_2 = x_809; color.y = (f32(x_230) + x_234); - let x_810 : f32 = x_209; - x_209 = 0.0; - x_209 = x_810; + let x_810 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_810; } - let x_237 : ptr = uv[0]; + let x_237 : ptr = &(uv[0]); let x_811 : i32 = i_2; i_2 = 0; i_2 = x_811; let x_467 : vec2 = vec2(x_191.x, x_191.x); - let x_812 : f32 = x_222; - x_222 = 0.0; - x_222 = x_812; - let x_238 : f32 = x_237; + let x_812 : f32 = *(x_222); + *(x_222) = 0.0; + *(x_222) = x_812; + let x_238 : f32 = *(x_237); let x_813 : vec3 = color; color = vec3(0.0, 0.0, 0.0); color = x_813; - let x_814 : f32 = x_208; - x_208 = 0.0; - x_208 = x_814; + let x_814 : f32 = *(x_208); + *(x_208) = 0.0; + *(x_208) = x_814; if ((x_238 > 0.75)) { - let x_815 : f32 = x_205; - x_205 = 0.0; - x_205 = x_815; + let x_815 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_815; let x_245 : i32 = obj.numbers[3]; - let x_816 : f32 = x_208; - x_208 = 0.0; - x_208 = x_816; + let x_816 : f32 = *(x_208); + *(x_208) = 0.0; + *(x_208) = x_816; let x_817 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_817; let x_468 : vec3 = vec3(x_467.x, x_467.x, x_467.x); - let x_818 : f32 = x_237; - x_237 = 0.0; - x_237 = x_818; - let x_248 : ptr = color.z; - let x_819 : f32 = x_222; - x_222 = 0.0; - x_222 = x_819; - let x_249 : f32 = x_248; + let x_818 : f32 = *(x_237); + *(x_237) = 0.0; + *(x_237) = x_818; + let x_248 : ptr = &(color.z); + let x_819 : f32 = *(x_222); + *(x_222) = 0.0; + *(x_222) = x_819; + let x_249 : f32 = *(x_248); let x_820 : vec3 = color; color = vec3(0.0, 0.0, 0.0); color = x_820; let x_469 : vec3 = vec3(x_467.x, x_191.y, x_467.y); - let x_821 : f32 = x_248; - x_248 = 0.0; - x_248 = x_821; - let x_822 : i32 = x_200; - x_200 = 0; - x_200 = x_822; + let x_821 : f32 = *(x_248); + *(x_248) = 0.0; + *(x_248) = x_821; + let x_822 : i32 = *(x_200); + *(x_200) = 0; + *(x_200) = x_822; let x_470 : vec2 = vec2(vec2(0.0, 0.0).x, vec2(0.0, 0.0).y); - let x_823 : f32 = x_248; - x_248 = 0.0; - x_248 = x_823; + let x_823 : f32 = *(x_248); + *(x_248) = 0.0; + *(x_248) = x_823; color.z = (x_249 + f32(x_245)); let x_824 : vec2 = uv; uv = vec2(0.0, 0.0); uv = x_824; let x_471 : vec2 = vec2(x_470.y, x_470.y); } - let x_825 : f32 = x_237; - x_237 = 0.0; - x_237 = x_825; + let x_825 : f32 = *(x_237); + *(x_237) = 0.0; + *(x_237) = x_825; let x_472 : vec3 = vec3(x_454.x, x_454.y, x_454.y); - let x_253 : ptr = obj.numbers[4]; - let x_254 : i32 = x_253; - let x_826 : f32 = x_237; - x_237 = 0.0; - x_237 = x_826; + let x_253 : ptr = &(obj.numbers[4]); + let x_254 : i32 = *(x_253); + let x_826 : f32 = *(x_237); + *(x_237) = 0.0; + *(x_237) = x_826; let x_827 : vec3 = color; color = vec3(0.0, 0.0, 0.0); color = x_827; let x_473 : vec3 = vec3(x_446.y, x_453.x, x_453.x); - let x_828 : i32 = x_253; - x_253 = 0; - x_253 = x_828; - let x_256 : ptr = color.y; + let x_828 : i32 = *(x_253); + *(x_253) = 0; + *(x_253) = x_828; + let x_256 : ptr = &(color.y); let x_474 : vec2 = vec2(x_191.x, x_184.z); - let x_829 : f32 = x_209; - x_209 = 0.0; - x_209 = x_829; - let x_257 : f32 = x_256; - let x_830 : f32 = x_256; - x_256 = 0.0; - x_256 = x_830; + let x_829 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_829; + let x_257 : f32 = *(x_256); + let x_830 : f32 = *(x_256); + *(x_256) = 0.0; + *(x_256) = x_830; let x_475 : vec2 = vec2(x_467.x, x_450.x); - let x_831 : f32 = x_222; - x_222 = 0.0; - x_222 = x_831; - let x_259 : ptr = color.y; - let x_832 : f32 = x_205; - x_205 = 0.0; - x_205 = x_832; + let x_831 : f32 = *(x_222); + *(x_222) = 0.0; + *(x_222) = x_831; + let x_259 : ptr = &(color.y); + let x_832 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_832; let x_476 : vec2 = vec2(x_451.z, x_460.y); - x_259 = (x_257 + f32(x_254)); + *(x_259) = (x_257 + f32(x_254)); let x_477 : vec3 = vec3(vec2(0.0, 0.0).x, x_472.x, vec2(0.0, 0.0).y); - let x_833 : f32 = x_209; - x_209 = 0.0; - x_209 = x_833; - let x_260 : ptr = uv.y; - let x_834 : f32 = x_205; - x_205 = 0.0; - x_205 = x_834; + let x_833 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_833; + let x_260 : ptr = &(uv.y); + let x_834 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_834; let x_478 : vec2 = vec2(x_472.x, x_472.y); - let x_835 : f32 = x_260; - x_260 = 0.0; - x_260 = x_835; - let x_261 : f32 = x_260; + let x_835 : f32 = *(x_260); + *(x_260) = 0.0; + *(x_260) = x_835; + let x_261 : f32 = *(x_260); let x_836 : i32 = i_2; i_2 = 0; i_2 = x_836; let x_479 : vec3 = vec3(vec2(0.0, 0.0).y, x_454.y, vec2(0.0, 0.0).x); - let x_837 : i32 = x_200; - x_200 = 0; - x_200 = x_837; - let x_838 : f32 = x_259; - x_259 = 0.0; - x_259 = x_838; + let x_837 : i32 = *(x_200); + *(x_200) = 0; + *(x_200) = x_837; + let x_838 : f32 = *(x_259); + *(x_259) = 0.0; + *(x_259) = x_838; let x_480 : vec3 = vec3(x_446.x, x_446.x, vec2(0.0, 0.0).y); - let x_839 : f32 = x_209; - x_209 = 0.0; - x_209 = x_839; + let x_839 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_839; if ((x_261 > 0.25)) { let x_481 : vec2 = vec2(x_447.x, x_480.z); let x_840 : vec3 = color; color = vec3(0.0, 0.0, 0.0); color = x_840; let x_267 : i32 = obj.numbers[5u]; - let x_841 : f32 = x_205; - x_205 = 0.0; - x_205 = x_841; + let x_841 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_841; let x_842 : i32 = i_2; i_2 = 0; i_2 = x_842; @@ -1148,172 +1148,172 @@ fn main() { i_2 = 0; i_2 = x_843; let x_270 : f32 = color.x; - let x_844 : f32 = x_237; - x_237 = 0.0; - x_237 = x_844; + let x_844 : f32 = *(x_237); + *(x_237) = 0.0; + *(x_237) = x_844; let x_482 : vec3 = vec3(x_455.x, x_475.y, x_455.y); let x_845 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_845; - let x_846 : f32 = x_260; - x_260 = 0.0; - x_260 = x_846; + let x_846 : f32 = *(x_260); + *(x_260) = 0.0; + *(x_260) = x_846; let x_847 : i32 = i_2; i_2 = 0; i_2 = x_847; let x_483 : vec3 = vec3(x_184.w, x_184.w, x_192.x); - let x_848 : f32 = x_209; - x_209 = 0.0; - x_209 = x_848; + let x_848 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_848; color.x = (f32(x_267) + x_270); let x_484 : vec3 = vec3(x_454.y, x_450.x, x_454.y); - let x_849 : f32 = x_209; - x_209 = 0.0; - x_209 = x_849; + let x_849 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_849; } - let x_850 : f32 = x_205; - x_205 = 0.0; - x_205 = x_850; + let x_850 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_850; let x_485 : vec3 = vec3(x_467.x, x_450.y, x_450.x); - let x_851 : f32 = x_260; - x_260 = 0.0; - x_260 = x_851; - let x_273 : ptr = uv.y; - let x_852 : i32 = x_253; - x_253 = 0; - x_253 = x_852; - let x_274 : f32 = x_273; - let x_853 : i32 = x_200; - x_200 = 0; - x_200 = x_853; + let x_851 : f32 = *(x_260); + *(x_260) = 0.0; + *(x_260) = x_851; + let x_273 : ptr = &(uv.y); + let x_852 : i32 = *(x_253); + *(x_253) = 0; + *(x_253) = x_852; + let x_274 : f32 = *(x_273); + let x_853 : i32 = *(x_200); + *(x_200) = 0; + *(x_200) = x_853; if ((x_274 > 0.5)) { - let x_854 : f32 = x_222; - x_222 = 0.0; - x_222 = x_854; + let x_854 : f32 = *(x_222); + *(x_222) = 0.0; + *(x_222) = x_854; let x_486 : vec2 = vec2(x_480.y, x_455.y); - let x_279 : ptr = obj.numbers[6u]; - let x_855 : f32 = x_256; - x_256 = 0.0; - x_256 = x_855; + let x_279 : ptr = &(obj.numbers[6u]); + let x_855 : f32 = *(x_256); + *(x_256) = 0.0; + *(x_256) = x_855; let x_487 : vec2 = vec2(x_449.z, x_449.y); - let x_856 : f32 = x_273; - x_273 = 0.0; - x_273 = x_856; - let x_280 : i32 = x_279; - let x_857 : f32 = x_260; - x_260 = 0.0; - x_260 = x_857; + let x_856 : f32 = *(x_273); + *(x_273) = 0.0; + *(x_273) = x_856; + let x_280 : i32 = *(x_279); + let x_857 : f32 = *(x_260); + *(x_260) = 0.0; + *(x_260) = x_857; let x_858 : i32 = i_2; i_2 = 0; i_2 = x_858; - let x_859 : i32 = x_253; - x_253 = 0; - x_253 = x_859; + let x_859 : i32 = *(x_253); + *(x_253) = 0; + *(x_253) = x_859; let x_488 : vec2 = vec2(x_473.z, x_473.y); let x_283 : f32 = color.y; let x_860 : vec2 = uv; uv = vec2(0.0, 0.0); uv = x_860; - let x_861 : f32 = x_208; - x_208 = 0.0; - x_208 = x_861; + let x_861 : f32 = *(x_208); + *(x_208) = 0.0; + *(x_208) = x_861; let x_489 : vec2 = vec2(x_475.y, x_475.x); - let x_862 : i32 = x_279; - x_279 = 0; - x_279 = x_862; - let x_863 : i32 = x_279; - x_279 = 0; - x_279 = x_863; + let x_862 : i32 = *(x_279); + *(x_279) = 0; + *(x_279) = x_862; + let x_863 : i32 = *(x_279); + *(x_279) = 0; + *(x_279) = x_863; let x_490 : vec2 = vec2(x_480.z, x_480.z); let x_864 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_864; color.y = (f32(x_280) + x_283); - let x_865 : f32 = x_208; - x_208 = 0.0; - x_208 = x_865; + let x_865 : f32 = *(x_208); + *(x_208) = 0.0; + *(x_208) = x_865; let x_491 : vec2 = vec2(vec3(1.0, 2.0, 3.0).y, x_454.x); - let x_866 : f32 = x_259; - x_259 = 0.0; - x_259 = x_866; + let x_866 : f32 = *(x_259); + *(x_259) = 0.0; + *(x_259) = x_866; } let x_492 : vec2 = vec2(x_455.y, x_455.y); - let x_867 : f32 = x_205; - x_205 = 0.0; - x_205 = x_867; - let x_286 : ptr = uv.y; - let x_287 : f32 = x_286; + let x_867 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_867; + let x_286 : ptr = &(uv.y); + let x_287 : f32 = *(x_286); let x_868 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_868; let x_493 : vec2 = vec2(x_475.x, x_475.y); - let x_869 : f32 = x_237; - x_237 = 0.0; - x_237 = x_869; - let x_870 : f32 = x_259; - x_259 = 0.0; - x_259 = x_870; + let x_869 : f32 = *(x_237); + *(x_237) = 0.0; + *(x_237) = x_869; + let x_870 : f32 = *(x_259); + *(x_259) = 0.0; + *(x_259) = x_870; let x_494 : vec3 = vec3(x_191.x, x_191.y, x_191.y); - let x_871 : i32 = x_253; - x_253 = 0; - x_253 = x_871; + let x_871 : i32 = *(x_253); + *(x_253) = 0; + *(x_253) = x_871; if ((x_287 > 0.75)) { let x_872 : vec3 = color; color = vec3(0.0, 0.0, 0.0); color = x_872; - let x_873 : f32 = x_208; - x_208 = 0.0; - x_208 = x_873; + let x_873 : f32 = *(x_208); + *(x_208) = 0.0; + *(x_208) = x_873; let x_495 : vec3 = vec3(x_192.y, x_192.x, x_192.y); let x_874 : vec3 = color; color = vec3(0.0, 0.0, 0.0); color = x_874; let x_293 : i32 = obj.numbers[7]; - let x_875 : f32 = x_222; - x_222 = 0.0; - x_222 = x_875; + let x_875 : f32 = *(x_222); + *(x_222) = 0.0; + *(x_222) = x_875; let x_496 : vec3 = vec3(x_475.x, x_467.y, x_467.x); - let x_876 : f32 = x_259; - x_259 = 0.0; - x_259 = x_876; + let x_876 : f32 = *(x_259); + *(x_259) = 0.0; + *(x_259) = x_876; let x_497 : vec2 = vec2(x_477.x, x_461.y); - let x_877 : i32 = x_200; - x_200 = 0; - x_200 = x_877; - let x_878 : f32 = x_259; - x_259 = 0.0; - x_259 = x_878; + let x_877 : i32 = *(x_200); + *(x_200) = 0; + *(x_200) = x_877; + let x_878 : f32 = *(x_259); + *(x_259) = 0.0; + *(x_259) = x_878; let x_498 : vec3 = vec3(x_478.x, x_478.y, x_478.x); - let x_879 : f32 = x_205; - x_205 = 0.0; - x_205 = x_879; + let x_879 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_879; let x_296 : f32 = color.z; - let x_880 : f32 = x_273; - x_273 = 0.0; - x_273 = x_880; + let x_880 : f32 = *(x_273); + *(x_273) = 0.0; + *(x_273) = x_880; let x_499 : vec2 = vec2(x_184.x, x_184.y); - let x_881 : f32 = x_209; - x_209 = 0.0; - x_209 = x_881; - let x_882 : f32 = x_286; - x_286 = 0.0; - x_286 = x_882; - let x_298 : ptr = color.z; - let x_883 : f32 = x_273; - x_273 = 0.0; - x_273 = x_883; + let x_881 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_881; + let x_882 : f32 = *(x_286); + *(x_286) = 0.0; + *(x_286) = x_882; + let x_298 : ptr = &(color.z); + let x_883 : f32 = *(x_273); + *(x_273) = 0.0; + *(x_273) = x_883; let x_500 : vec3 = vec3(x_499.y, x_499.y, x_494.z); - let x_884 : f32 = x_298; - x_298 = 0.0; - x_298 = x_884; - x_298 = (f32(x_293) + x_296); - let x_885 : f32 = x_256; - x_256 = 0.0; - x_256 = x_885; + let x_884 : f32 = *(x_298); + *(x_298) = 0.0; + *(x_298) = x_884; + *(x_298) = (f32(x_293) + x_296); + let x_885 : f32 = *(x_256); + *(x_256) = 0.0; + *(x_256) = x_885; let x_501 : vec2 = vec2(x_453.x, x_453.z); - let x_886 : f32 = x_205; - x_205 = 0.0; - x_205 = x_886; + let x_886 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_886; } let x_887 : i32 = i_2; i_2 = 0; @@ -1322,74 +1322,74 @@ fn main() { let x_888 : vec2 = uv; uv = vec2(0.0, 0.0); uv = x_888; - let x_300 : ptr = obj.numbers[8]; - let x_301 : i32 = x_300; + let x_300 : ptr = &(obj.numbers[8]); + let x_301 : i32 = *(x_300); let x_889 : i32 = i_2; i_2 = 0; i_2 = x_889; let x_503 : vec2 = vec2(x_185.x, x_451.z); - let x_890 : i32 = x_300; - x_300 = 0; - x_300 = x_890; - let x_891 : f32 = x_256; - x_256 = 0.0; - x_256 = x_891; + let x_890 : i32 = *(x_300); + *(x_300) = 0; + *(x_300) = x_890; + let x_891 : f32 = *(x_256); + *(x_256) = 0.0; + *(x_256) = x_891; let x_504 : vec2 = vec2(x_453.y, vec2(0.0, 0.0).x); - let x_892 : f32 = x_205; - x_205 = 0.0; - x_205 = x_892; - let x_303 : ptr = color.z; + let x_892 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_892; + let x_303 : ptr = &(color.z); let x_505 : vec3 = vec3(x_504.x, x_504.y, x_504.x); - let x_893 : f32 = x_303; - x_303 = 0.0; - x_303 = x_893; - let x_304 : f32 = x_303; - let x_894 : f32 = x_208; - x_208 = 0.0; - x_208 = x_894; + let x_893 : f32 = *(x_303); + *(x_303) = 0.0; + *(x_303) = x_893; + let x_304 : f32 = *(x_303); + let x_894 : f32 = *(x_208); + *(x_208) = 0.0; + *(x_208) = x_894; let x_506 : vec2 = vec2(x_493.x, x_492.x); - let x_895 : i32 = x_253; - x_253 = 0; - x_253 = x_895; - let x_896 : f32 = x_286; - x_286 = 0.0; - x_286 = x_896; + let x_895 : i32 = *(x_253); + *(x_253) = 0; + *(x_253) = x_895; + let x_896 : f32 = *(x_286); + *(x_286) = 0.0; + *(x_286) = x_896; let x_507 : vec2 = vec2(x_461.x, x_447.x); - let x_897 : f32 = x_259; - x_259 = 0.0; - x_259 = x_897; - let x_306 : ptr = color.z; - x_306 = (x_304 + f32(x_301)); + let x_897 : f32 = *(x_259); + *(x_259) = 0.0; + *(x_259) = x_897; + let x_306 : ptr = &(color.z); + *(x_306) = (x_304 + f32(x_301)); let x_898 : vec2 = uv; uv = vec2(0.0, 0.0); uv = x_898; - let x_899 : f32 = x_222; - x_222 = 0.0; - x_222 = x_899; + let x_899 : f32 = *(x_222); + *(x_222) = 0.0; + *(x_222) = x_899; let x_508 : vec3 = vec3(x_461.y, x_461.x, x_506.y); - let x_900 : f32 = x_222; - x_222 = 0.0; - x_222 = x_900; + let x_900 : f32 = *(x_222); + *(x_222) = 0.0; + *(x_222) = x_900; let x_308 : f32 = uv.x; - let x_901 : f32 = x_259; - x_259 = 0.0; - x_259 = x_901; - let x_309 : ptr = uv.y; + let x_901 : f32 = *(x_259); + *(x_259) = 0.0; + *(x_259) = x_901; + let x_309 : ptr = &(uv.y); let x_509 : vec3 = vec3(x_503.y, x_503.x, x_448.z); - let x_902 : f32 = x_260; - x_260 = 0.0; - x_260 = x_902; - let x_310 : f32 = x_309; - let x_903 : f32 = x_260; - x_260 = 0.0; - x_260 = x_903; - let x_904 : f32 = x_306; - x_306 = 0.0; - x_306 = x_904; + let x_902 : f32 = *(x_260); + *(x_260) = 0.0; + *(x_260) = x_902; + let x_310 : f32 = *(x_309); + let x_903 : f32 = *(x_260); + *(x_260) = 0.0; + *(x_260) = x_903; + let x_904 : f32 = *(x_306); + *(x_306) = 0.0; + *(x_306) = x_904; let x_510 : vec3 = vec3(vec3(1.0, 2.0, 3.0).y, x_485.y, x_485.z); - let x_905 : f32 = x_306; - x_306 = 0.0; - x_306 = x_905; + let x_905 : f32 = *(x_306); + *(x_306) = 0.0; + *(x_306) = x_905; let x_906 : i32 = i_2; i_2 = 0; i_2 = x_906; @@ -1397,37 +1397,37 @@ fn main() { let x_907 : vec3 = color; color = vec3(0.0, 0.0, 0.0); color = x_907; - let x_908 : f32 = x_260; - x_260 = 0.0; - x_260 = x_908; + let x_908 : f32 = *(x_260); + *(x_260) = 0.0; + *(x_260) = x_908; let x_512 : vec3 = vec3(x_455.y, x_455.y, x_455.y); - let x_909 : i32 = x_253; - x_253 = 0; - x_253 = x_909; + let x_909 : i32 = *(x_253); + *(x_253) = 0; + *(x_253) = x_909; if ((abs((x_308 - x_310)) < 0.25)) { - let x_910 : f32 = x_209; - x_209 = 0.0; - x_209 = x_910; + let x_910 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_910; let x_911 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_911; let x_513 : vec3 = vec3(x_505.z, x_505.x, x_448.x); - let x_912 : i32 = x_300; - x_300 = 0; - x_300 = x_912; + let x_912 : i32 = *(x_300); + *(x_300) = 0; + *(x_300) = x_912; let x_317 : i32 = obj.numbers[9u]; let x_514 : vec3 = vec3(x_474.y, x_474.y, x_474.y); - let x_913 : f32 = x_260; - x_260 = 0.0; - x_260 = x_913; + let x_913 : f32 = *(x_260); + *(x_260) = 0.0; + *(x_260) = x_913; let x_320 : f32 = color.x; - let x_914 : f32 = x_286; - x_286 = 0.0; - x_286 = x_914; + let x_914 : f32 = *(x_286); + *(x_286) = 0.0; + *(x_286) = x_914; let x_515 : vec2 = vec2(x_502.x, x_502.y); - let x_915 : f32 = x_205; - x_205 = 0.0; - x_205 = x_915; + let x_915 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_915; let x_916 : vec3 = color; color = vec3(0.0, 0.0, 0.0); color = x_916; @@ -1435,60 +1435,60 @@ fn main() { let x_917 : vec2 = uv; uv = vec2(0.0, 0.0); uv = x_917; - let x_322 : ptr = color.x; - let x_918 : f32 = x_209; - x_209 = 0.0; - x_209 = x_918; + let x_322 : ptr = &(color.x); + let x_918 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_918; let x_517 : vec3 = vec3(vec2(0.0, 0.0).x, vec2(0.0, 0.0).x, vec2(0.0, 0.0).y); - x_322 = (f32(x_317) + x_320); - let x_919 : f32 = x_322; - x_322 = 0.0; - x_322 = x_919; + *(x_322) = (f32(x_317) + x_320); + let x_919 : f32 = *(x_322); + *(x_322) = 0.0; + *(x_322) = x_919; let x_518 : vec3 = vec3(x_480.y, x_508.x, x_480.x); - let x_920 : f32 = x_205; - x_205 = 0.0; - x_205 = x_920; + let x_920 : f32 = *(x_205); + *(x_205) = 0.0; + *(x_205) = x_920; } - let x_921 : f32 = x_309; - x_309 = 0.0; - x_309 = x_921; + let x_921 : f32 = *(x_309); + *(x_309) = 0.0; + *(x_309) = x_921; let x_325 : vec3 = color; - let x_922 : f32 = x_237; - x_237 = 0.0; - x_237 = x_922; + let x_922 : f32 = *(x_237); + *(x_237) = 0.0; + *(x_237) = x_922; let x_519 : vec3 = vec3(x_447.x, x_446.x, x_446.y); let x_326 : vec3 = normalize(x_325); - let x_923 : f32 = x_209; - x_209 = 0.0; - x_209 = x_923; + let x_923 : f32 = *(x_209); + *(x_209) = 0.0; + *(x_209) = x_923; let x_924 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_924; let x_925 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_925; - let x_926 : f32 = x_259; - x_259 = 0.0; - x_259 = x_926; + let x_926 : f32 = *(x_259); + *(x_259) = 0.0; + *(x_259) = x_926; let x_520 : vec2 = vec2(x_506.y, x_519.y); - let x_927 : f32 = x_259; - x_259 = 0.0; - x_259 = x_927; + let x_927 : f32 = *(x_259); + *(x_259) = 0.0; + *(x_259) = x_927; let x_330 : vec4 = vec4(x_326.x, x_326.y, x_326.z, 1.0); - let x_928 : f32 = x_309; - x_309 = 0.0; - x_309 = x_928; + let x_928 : f32 = *(x_309); + *(x_309) = 0.0; + *(x_309) = x_928; let x_521 : vec3 = vec3(vec3(1.0, 2.0, 3.0).y, vec3(1.0, 2.0, 3.0).y, x_520.y); - let x_929 : f32 = x_222; - x_222 = 0.0; - x_222 = x_929; + let x_929 : f32 = *(x_222); + *(x_222) = 0.0; + *(x_222) = x_929; x_GLF_color = x_330; let x_930 : QuicksortObject = obj; obj = QuicksortObject(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); obj = x_930; let x_522 : vec3 = vec3(x_330.w, x_330.y, x_493.x); - let x_931 : f32 = x_208; - x_208 = 0.0; - x_208 = x_931; + let x_931 : f32 = *(x_208); + *(x_208) = 0.0; + *(x_208) = x_931; return; } diff --git a/test/intrinsics/arrayLength.wgsl b/test/intrinsics/arrayLength.wgsl new file mode 100644 index 0000000000..6ee682871d --- /dev/null +++ b/test/intrinsics/arrayLength.wgsl @@ -0,0 +1,12 @@ +[[block]] +struct S { + a : array; +}; + +[[group(0), binding(0)]] var G : [[access(read)]] S; + +[[stage(compute)]] +fn main() { + // TODO(crbug.com/tint/806): arrayLength signature is currently wrong + // let l : i32 = arrayLength(&G.a); +} diff --git a/test/intrinsics/arrayLength.wgsl.expected.hlsl b/test/intrinsics/arrayLength.wgsl.expected.hlsl new file mode 100644 index 0000000000..b3fc631c5e --- /dev/null +++ b/test/intrinsics/arrayLength.wgsl.expected.hlsl @@ -0,0 +1,6 @@ + +[numthreads(1, 1, 1)] +void main() { + return; +} + diff --git a/test/intrinsics/arrayLength.wgsl.expected.msl b/test/intrinsics/arrayLength.wgsl.expected.msl new file mode 100644 index 0000000000..a43de5c874 --- /dev/null +++ b/test/intrinsics/arrayLength.wgsl.expected.msl @@ -0,0 +1,11 @@ +#include + +using namespace metal; +struct S { + /* 0x0000 */ int a[1]; +}; + +kernel void tint_symbol() { + return; +} + diff --git a/test/intrinsics/arrayLength.wgsl.expected.spvasm b/test/intrinsics/arrayLength.wgsl.expected.spvasm new file mode 100644 index 0000000000..bf2a83a116 --- /dev/null +++ b/test/intrinsics/arrayLength.wgsl.expected.spvasm @@ -0,0 +1,30 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 10 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %S "S" + OpMemberName %S 0 "a" + OpName %G "G" + OpName %main "main" + OpDecorate %S Block + OpMemberDecorate %S 0 Offset 0 + OpDecorate %_runtimearr_int ArrayStride 4 + OpDecorate %G NonWritable + OpDecorate %G DescriptorSet 0 + OpDecorate %G Binding 0 + %int = OpTypeInt 32 1 +%_runtimearr_int = OpTypeRuntimeArray %int + %S = OpTypeStruct %_runtimearr_int +%_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S + %G = OpVariable %_ptr_StorageBuffer_S StorageBuffer + %void = OpTypeVoid + %6 = OpTypeFunction %void + %main = OpFunction %void None %6 + %9 = OpLabel + OpReturn + OpFunctionEnd diff --git a/test/intrinsics/arrayLength.wgsl.expected.wgsl b/test/intrinsics/arrayLength.wgsl.expected.wgsl new file mode 100644 index 0000000000..5f75515a74 --- /dev/null +++ b/test/intrinsics/arrayLength.wgsl.expected.wgsl @@ -0,0 +1,10 @@ +[[block]] +struct S { + a : array; +}; + +[[group(0), binding(0)]] var G : [[access(read)]] S; + +[[stage(compute)]] +fn main() { +} diff --git a/test/intrinsics/frexp.wgsl b/test/intrinsics/frexp.wgsl new file mode 100644 index 0000000000..2e0ea4beab --- /dev/null +++ b/test/intrinsics/frexp.wgsl @@ -0,0 +1,5 @@ +[[stage(compute)]] +fn main() { + var exponent : i32; + let significand : f32 = frexp(1.23, &exponent); +} diff --git a/test/intrinsics/frexp.wgsl.expected.hlsl b/test/intrinsics/frexp.wgsl.expected.hlsl new file mode 100644 index 0000000000..e0f2632880 --- /dev/null +++ b/test/intrinsics/frexp.wgsl.expected.hlsl @@ -0,0 +1 @@ +SKIP: Failed to generate: error: Unknown builtin method: frexp diff --git a/test/intrinsics/frexp.wgsl.expected.msl b/test/intrinsics/frexp.wgsl.expected.msl new file mode 100644 index 0000000000..06c7a47ffe --- /dev/null +++ b/test/intrinsics/frexp.wgsl.expected.msl @@ -0,0 +1 @@ +SKIP: Failed to generate: error: Unknown import method: frexp \ No newline at end of file diff --git a/test/intrinsics/frexp.wgsl.expected.spvasm b/test/intrinsics/frexp.wgsl.expected.spvasm new file mode 100644 index 0000000000..7d6543e218 --- /dev/null +++ b/test/intrinsics/frexp.wgsl.expected.spvasm @@ -0,0 +1,25 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 14 +; Schema: 0 + OpCapability Shader + %11 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %exponent "exponent" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %8 = OpConstantNull %int + %float = OpTypeFloat 32 +%float_1_23000002 = OpConstant %float 1.23000002 + %main = OpFunction %void None %1 + %4 = OpLabel + %exponent = OpVariable %_ptr_Function_int Function %8 + %9 = OpExtInst %float %11 Frexp %float_1_23000002 %exponent + OpReturn + OpFunctionEnd diff --git a/test/intrinsics/frexp.wgsl.expected.wgsl b/test/intrinsics/frexp.wgsl.expected.wgsl new file mode 100644 index 0000000000..9a8ad1d81c --- /dev/null +++ b/test/intrinsics/frexp.wgsl.expected.wgsl @@ -0,0 +1,5 @@ +[[stage(compute)]] +fn main() { + var exponent : i32; + let significand : f32 = frexp(1.230000019, &(exponent)); +} diff --git a/test/intrinsics/modf.wgsl b/test/intrinsics/modf.wgsl new file mode 100644 index 0000000000..735c360c10 --- /dev/null +++ b/test/intrinsics/modf.wgsl @@ -0,0 +1,5 @@ +[[stage(compute)]] +fn main() { + var whole : f32; + let frac : f32 = modf(1.23, &whole); +} diff --git a/test/intrinsics/modf.wgsl.expected.hlsl b/test/intrinsics/modf.wgsl.expected.hlsl new file mode 100644 index 0000000000..e0f2632880 --- /dev/null +++ b/test/intrinsics/modf.wgsl.expected.hlsl @@ -0,0 +1 @@ +SKIP: Failed to generate: error: Unknown builtin method: frexp diff --git a/test/intrinsics/modf.wgsl.expected.msl b/test/intrinsics/modf.wgsl.expected.msl new file mode 100644 index 0000000000..06c7a47ffe --- /dev/null +++ b/test/intrinsics/modf.wgsl.expected.msl @@ -0,0 +1 @@ +SKIP: Failed to generate: error: Unknown import method: frexp \ No newline at end of file diff --git a/test/intrinsics/modf.wgsl.expected.spvasm b/test/intrinsics/modf.wgsl.expected.spvasm new file mode 100644 index 0000000000..090d8b8946 --- /dev/null +++ b/test/intrinsics/modf.wgsl.expected.spvasm @@ -0,0 +1,24 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 13 +; Schema: 0 + OpCapability Shader + %10 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %whole "whole" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %float = OpTypeFloat 32 +%_ptr_Function_float = OpTypePointer Function %float + %8 = OpConstantNull %float +%float_1_23000002 = OpConstant %float 1.23000002 + %main = OpFunction %void None %1 + %4 = OpLabel + %whole = OpVariable %_ptr_Function_float Function %8 + %9 = OpExtInst %float %10 Modf %float_1_23000002 %whole + OpReturn + OpFunctionEnd diff --git a/test/intrinsics/modf.wgsl.expected.wgsl b/test/intrinsics/modf.wgsl.expected.wgsl new file mode 100644 index 0000000000..9f7ea1ff10 --- /dev/null +++ b/test/intrinsics/modf.wgsl.expected.wgsl @@ -0,0 +1,5 @@ +[[stage(compute)]] +fn main() { + var whole : f32; + let frac : f32 = modf(1.230000019, &(whole)); +} diff --git a/test/ptr_ref/access/matrix.spvasm b/test/ptr_ref/access/matrix.spvasm new file mode 100644 index 0000000000..f29e412caf --- /dev/null +++ b/test/ptr_ref/access/matrix.spvasm @@ -0,0 +1,43 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 31 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %m "m" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v3float = OpTypeVector %float 3 +%mat3v3float = OpTypeMatrix %v3float 3 + %float_1 = OpConstant %float 1 + %float_2 = OpConstant %float 2 + %float_3 = OpConstant %float 3 + %11 = OpConstantComposite %v3float %float_1 %float_2 %float_3 + %float_4 = OpConstant %float 4 + %float_5 = OpConstant %float 5 + %float_6 = OpConstant %float 6 + %15 = OpConstantComposite %v3float %float_4 %float_5 %float_6 + %float_7 = OpConstant %float 7 + %float_8 = OpConstant %float 8 + %float_9 = OpConstant %float 9 + %19 = OpConstantComposite %v3float %float_7 %float_8 %float_9 + %20 = OpConstantComposite %mat3v3float %11 %15 %19 +%_ptr_Function_mat3v3float = OpTypePointer Function %mat3v3float + %23 = OpConstantNull %mat3v3float + %int = OpTypeInt 32 1 + %int_1 = OpConstant %int 1 +%_ptr_Function_v3float = OpTypePointer Function %v3float + %30 = OpConstantComposite %v3float %float_5 %float_5 %float_5 + %main = OpFunction %void None %1 + %4 = OpLabel + %m = OpVariable %_ptr_Function_mat3v3float Function %23 + OpStore %m %20 + %28 = OpAccessChain %_ptr_Function_v3float %m %int_1 + OpStore %28 %30 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/access/matrix.spvasm.expected.hlsl b/test/ptr_ref/access/matrix.spvasm.expected.hlsl new file mode 100644 index 0000000000..b3db42f63d --- /dev/null +++ b/test/ptr_ref/access/matrix.spvasm.expected.hlsl @@ -0,0 +1 @@ +SKIP: Failed to generate: error: pointers not supported in HLSL diff --git a/test/ptr_ref/access/matrix.spvasm.expected.msl b/test/ptr_ref/access/matrix.spvasm.expected.msl new file mode 100644 index 0000000000..beac5b502e --- /dev/null +++ b/test/ptr_ref/access/matrix.spvasm.expected.msl @@ -0,0 +1,10 @@ +#include + +using namespace metal; +kernel void tint_symbol() { + float3x3 m = float3x3(float3(0.0f, 0.0f, 0.0f), float3(0.0f, 0.0f, 0.0f), float3(0.0f, 0.0f, 0.0f)); + m = float3x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f)); + m[1] = float3(5.0f, 5.0f, 5.0f); + return; +} + diff --git a/test/ptr_ref/access/matrix.spvasm.expected.spvasm b/test/ptr_ref/access/matrix.spvasm.expected.spvasm new file mode 100644 index 0000000000..762777bf00 --- /dev/null +++ b/test/ptr_ref/access/matrix.spvasm.expected.spvasm @@ -0,0 +1,47 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 32 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %m "m" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v3float = OpTypeVector %float 3 +%mat3v3float = OpTypeMatrix %v3float 3 + %float_0 = OpConstant %float 0 + %9 = OpConstantComposite %v3float %float_0 %float_0 %float_0 + %10 = OpConstantComposite %mat3v3float %9 %9 %9 +%_ptr_Function_mat3v3float = OpTypePointer Function %mat3v3float + %13 = OpConstantNull %mat3v3float + %float_1 = OpConstant %float 1 + %float_2 = OpConstant %float 2 + %float_3 = OpConstant %float 3 + %17 = OpConstantComposite %v3float %float_1 %float_2 %float_3 + %float_4 = OpConstant %float 4 + %float_5 = OpConstant %float 5 + %float_6 = OpConstant %float 6 + %21 = OpConstantComposite %v3float %float_4 %float_5 %float_6 + %float_7 = OpConstant %float 7 + %float_8 = OpConstant %float 8 + %float_9 = OpConstant %float 9 + %25 = OpConstantComposite %v3float %float_7 %float_8 %float_9 + %26 = OpConstantComposite %mat3v3float %17 %21 %25 + %int = OpTypeInt 32 1 + %int_1 = OpConstant %int 1 +%_ptr_Function_v3float = OpTypePointer Function %v3float + %31 = OpConstantComposite %v3float %float_5 %float_5 %float_5 + %main = OpFunction %void None %1 + %4 = OpLabel + %m = OpVariable %_ptr_Function_mat3v3float Function %13 + OpStore %m %10 + OpStore %m %26 + %30 = OpAccessChain %_ptr_Function_v3float %m %int_1 + OpStore %30 %31 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/access/matrix.spvasm.expected.wgsl b/test/ptr_ref/access/matrix.spvasm.expected.wgsl new file mode 100644 index 0000000000..dabe5d49e2 --- /dev/null +++ b/test/ptr_ref/access/matrix.spvasm.expected.wgsl @@ -0,0 +1,7 @@ +[[stage(compute)]] +fn main() { + var m : mat3x3 = mat3x3(vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 0.0)); + m = mat3x3(vec3(1.0, 2.0, 3.0), vec3(4.0, 5.0, 6.0), vec3(7.0, 8.0, 9.0)); + m[1] = vec3(5.0, 5.0, 5.0); + return; +} diff --git a/test/ptr_ref/access/matrix.wgsl b/test/ptr_ref/access/matrix.wgsl new file mode 100644 index 0000000000..5ec6915138 --- /dev/null +++ b/test/ptr_ref/access/matrix.wgsl @@ -0,0 +1,6 @@ +[[stage(compute)]] +fn main() { + var m : mat3x3 = mat3x3(vec3(1., 2., 3.), vec3(4., 5., 6.), vec3(7., 8., 9.)); + let v : ptr> = &m[1]; + *v = vec3(5., 5., 5.); +} diff --git a/test/ptr_ref/access/matrix.wgsl.expected.hlsl b/test/ptr_ref/access/matrix.wgsl.expected.hlsl new file mode 100644 index 0000000000..b3db42f63d --- /dev/null +++ b/test/ptr_ref/access/matrix.wgsl.expected.hlsl @@ -0,0 +1 @@ +SKIP: Failed to generate: error: pointers not supported in HLSL diff --git a/test/ptr_ref/access/matrix.wgsl.expected.msl b/test/ptr_ref/access/matrix.wgsl.expected.msl new file mode 100644 index 0000000000..5bf9bb9a15 --- /dev/null +++ b/test/ptr_ref/access/matrix.wgsl.expected.msl @@ -0,0 +1,10 @@ +#include + +using namespace metal; +kernel void tint_symbol() { + float3x3 m = float3x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f)); + float3* const v = &(m[1]); + *(v) = float3(5.0f, 5.0f, 5.0f); + return; +} + diff --git a/test/ptr_ref/access/matrix.wgsl.expected.spvasm b/test/ptr_ref/access/matrix.wgsl.expected.spvasm new file mode 100644 index 0000000000..f29e412caf --- /dev/null +++ b/test/ptr_ref/access/matrix.wgsl.expected.spvasm @@ -0,0 +1,43 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 31 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %m "m" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v3float = OpTypeVector %float 3 +%mat3v3float = OpTypeMatrix %v3float 3 + %float_1 = OpConstant %float 1 + %float_2 = OpConstant %float 2 + %float_3 = OpConstant %float 3 + %11 = OpConstantComposite %v3float %float_1 %float_2 %float_3 + %float_4 = OpConstant %float 4 + %float_5 = OpConstant %float 5 + %float_6 = OpConstant %float 6 + %15 = OpConstantComposite %v3float %float_4 %float_5 %float_6 + %float_7 = OpConstant %float 7 + %float_8 = OpConstant %float 8 + %float_9 = OpConstant %float 9 + %19 = OpConstantComposite %v3float %float_7 %float_8 %float_9 + %20 = OpConstantComposite %mat3v3float %11 %15 %19 +%_ptr_Function_mat3v3float = OpTypePointer Function %mat3v3float + %23 = OpConstantNull %mat3v3float + %int = OpTypeInt 32 1 + %int_1 = OpConstant %int 1 +%_ptr_Function_v3float = OpTypePointer Function %v3float + %30 = OpConstantComposite %v3float %float_5 %float_5 %float_5 + %main = OpFunction %void None %1 + %4 = OpLabel + %m = OpVariable %_ptr_Function_mat3v3float Function %23 + OpStore %m %20 + %28 = OpAccessChain %_ptr_Function_v3float %m %int_1 + OpStore %28 %30 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/access/matrix.wgsl.expected.wgsl b/test/ptr_ref/access/matrix.wgsl.expected.wgsl new file mode 100644 index 0000000000..f38b714abc --- /dev/null +++ b/test/ptr_ref/access/matrix.wgsl.expected.wgsl @@ -0,0 +1,6 @@ +[[stage(compute)]] +fn main() { + var m : mat3x3 = mat3x3(vec3(1.0, 2.0, 3.0), vec3(4.0, 5.0, 6.0), vec3(7.0, 8.0, 9.0)); + let v : ptr> = &(m[1]); + *(v) = vec3(5.0, 5.0, 5.0); +} diff --git a/test/ptr_ref/access/vector.spvasm b/test/ptr_ref/access/vector.spvasm new file mode 100644 index 0000000000..deada33645 --- /dev/null +++ b/test/ptr_ref/access/vector.spvasm @@ -0,0 +1,33 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 21 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %v "v" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v3float = OpTypeVector %float 3 + %float_1 = OpConstant %float 1 + %float_2 = OpConstant %float 2 + %float_3 = OpConstant %float 3 + %10 = OpConstantComposite %v3float %float_1 %float_2 %float_3 +%_ptr_Function_v3float = OpTypePointer Function %v3float + %13 = OpConstantNull %v3float + %uint = OpTypeInt 32 0 + %uint_1 = OpConstant %uint 1 +%_ptr_Function_float = OpTypePointer Function %float + %float_5 = OpConstant %float 5 + %main = OpFunction %void None %1 + %4 = OpLabel + %v = OpVariable %_ptr_Function_v3float Function %13 + OpStore %v %10 + %18 = OpAccessChain %_ptr_Function_float %v %uint_1 + OpStore %18 %float_5 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/access/vector.spvasm.expected.hlsl b/test/ptr_ref/access/vector.spvasm.expected.hlsl new file mode 100644 index 0000000000..b3db42f63d --- /dev/null +++ b/test/ptr_ref/access/vector.spvasm.expected.hlsl @@ -0,0 +1 @@ +SKIP: Failed to generate: error: pointers not supported in HLSL diff --git a/test/ptr_ref/access/vector.spvasm.expected.msl b/test/ptr_ref/access/vector.spvasm.expected.msl new file mode 100644 index 0000000000..650c7525d0 --- /dev/null +++ b/test/ptr_ref/access/vector.spvasm.expected.msl @@ -0,0 +1,10 @@ +#include + +using namespace metal; +kernel void tint_symbol() { + float3 v = float3(0.0f, 0.0f, 0.0f); + v = float3(1.0f, 2.0f, 3.0f); + v.y = 5.0f; + return; +} + diff --git a/test/ptr_ref/access/vector.spvasm.expected.spvasm b/test/ptr_ref/access/vector.spvasm.expected.spvasm new file mode 100644 index 0000000000..5d2c9155a9 --- /dev/null +++ b/test/ptr_ref/access/vector.spvasm.expected.spvasm @@ -0,0 +1,36 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 21 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %v "v" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v3float = OpTypeVector %float 3 + %float_0 = OpConstant %float 0 + %8 = OpConstantComposite %v3float %float_0 %float_0 %float_0 +%_ptr_Function_v3float = OpTypePointer Function %v3float + %11 = OpConstantNull %v3float + %float_1 = OpConstant %float 1 + %float_2 = OpConstant %float 2 + %float_3 = OpConstant %float 3 + %15 = OpConstantComposite %v3float %float_1 %float_2 %float_3 + %uint = OpTypeInt 32 0 + %uint_1 = OpConstant %uint 1 +%_ptr_Function_float = OpTypePointer Function %float + %float_5 = OpConstant %float 5 + %main = OpFunction %void None %1 + %4 = OpLabel + %v = OpVariable %_ptr_Function_v3float Function %11 + OpStore %v %8 + OpStore %v %15 + %19 = OpAccessChain %_ptr_Function_float %v %uint_1 + OpStore %19 %float_5 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/access/vector.spvasm.expected.wgsl b/test/ptr_ref/access/vector.spvasm.expected.wgsl new file mode 100644 index 0000000000..dce7b8f895 --- /dev/null +++ b/test/ptr_ref/access/vector.spvasm.expected.wgsl @@ -0,0 +1,7 @@ +[[stage(compute)]] +fn main() { + var v : vec3 = vec3(0.0, 0.0, 0.0); + v = vec3(1.0, 2.0, 3.0); + v.y = 5.0; + return; +} diff --git a/test/ptr_ref/access/vector.wgsl b/test/ptr_ref/access/vector.wgsl new file mode 100644 index 0000000000..779ebad553 --- /dev/null +++ b/test/ptr_ref/access/vector.wgsl @@ -0,0 +1,6 @@ +[[stage(compute)]] +fn main() { + var v : vec3 = vec3(1., 2., 3.); + let f : ptr = &v.y; + *f = 5.0; +} diff --git a/test/ptr_ref/access/vector.wgsl.expected.hlsl b/test/ptr_ref/access/vector.wgsl.expected.hlsl new file mode 100644 index 0000000000..b3db42f63d --- /dev/null +++ b/test/ptr_ref/access/vector.wgsl.expected.hlsl @@ -0,0 +1 @@ +SKIP: Failed to generate: error: pointers not supported in HLSL diff --git a/test/ptr_ref/access/vector.wgsl.expected.msl b/test/ptr_ref/access/vector.wgsl.expected.msl new file mode 100644 index 0000000000..88a1b99c98 --- /dev/null +++ b/test/ptr_ref/access/vector.wgsl.expected.msl @@ -0,0 +1,10 @@ +#include + +using namespace metal; +kernel void tint_symbol() { + float3 v = float3(1.0f, 2.0f, 3.0f); + float* const f = &(v.y); + *(f) = 5.0f; + return; +} + diff --git a/test/ptr_ref/access/vector.wgsl.expected.spvasm b/test/ptr_ref/access/vector.wgsl.expected.spvasm new file mode 100644 index 0000000000..deada33645 --- /dev/null +++ b/test/ptr_ref/access/vector.wgsl.expected.spvasm @@ -0,0 +1,33 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 21 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %v "v" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v3float = OpTypeVector %float 3 + %float_1 = OpConstant %float 1 + %float_2 = OpConstant %float 2 + %float_3 = OpConstant %float 3 + %10 = OpConstantComposite %v3float %float_1 %float_2 %float_3 +%_ptr_Function_v3float = OpTypePointer Function %v3float + %13 = OpConstantNull %v3float + %uint = OpTypeInt 32 0 + %uint_1 = OpConstant %uint 1 +%_ptr_Function_float = OpTypePointer Function %float + %float_5 = OpConstant %float 5 + %main = OpFunction %void None %1 + %4 = OpLabel + %v = OpVariable %_ptr_Function_v3float Function %13 + OpStore %v %10 + %18 = OpAccessChain %_ptr_Function_float %v %uint_1 + OpStore %18 %float_5 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/access/vector.wgsl.expected.wgsl b/test/ptr_ref/access/vector.wgsl.expected.wgsl new file mode 100644 index 0000000000..730c386397 --- /dev/null +++ b/test/ptr_ref/access/vector.wgsl.expected.wgsl @@ -0,0 +1,6 @@ +[[stage(compute)]] +fn main() { + var v : vec3 = vec3(1.0, 2.0, 3.0); + let f : ptr = &(v.y); + *(f) = 5.0; +} diff --git a/test/ptr_ref/copy/ptr_copy.spvasm b/test/ptr_ref/copy/ptr_copy.spvasm new file mode 100644 index 0000000000..1163cb10ef --- /dev/null +++ b/test/ptr_ref/copy/ptr_copy.spvasm @@ -0,0 +1,15 @@ + OpCapability Shader + OpMemoryModel Logical Simple + OpEntryPoint GLCompute %100 "main" + OpExecutionMode %100 LocalSize 1 1 1 + %uint = OpTypeInt 32 0 + %void = OpTypeVoid +%voidfn = OpTypeFunction %void + %ptr = OpTypePointer Function %uint + %100 = OpFunction %void None %voidfn + %entry = OpLabel + %10 = OpVariable %ptr Function + %1 = OpCopyObject %ptr %10 + %2 = OpCopyObject %ptr %1 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/copy/ptr_copy.spvasm.expected.hlsl b/test/ptr_ref/copy/ptr_copy.spvasm.expected.hlsl new file mode 100644 index 0000000000..16f9b25224 --- /dev/null +++ b/test/ptr_ref/copy/ptr_copy.spvasm.expected.hlsl @@ -0,0 +1 @@ +SKIP: error: pointers not supported in HLSL diff --git a/test/ptr_ref/copy/ptr_copy.spvasm.expected.msl b/test/ptr_ref/copy/ptr_copy.spvasm.expected.msl new file mode 100644 index 0000000000..ec58031418 --- /dev/null +++ b/test/ptr_ref/copy/ptr_copy.spvasm.expected.msl @@ -0,0 +1,10 @@ +#include + +using namespace metal; +kernel void tint_symbol() { + uint x_10 = 0u; + uint* const x_1 = &(x_10); + uint* const x_2 = x_1; + return; +} + diff --git a/test/ptr_ref/copy/ptr_copy.spvasm.expected.spvasm b/test/ptr_ref/copy/ptr_copy.spvasm.expected.spvasm new file mode 100644 index 0000000000..eeebd89b47 --- /dev/null +++ b/test/ptr_ref/copy/ptr_copy.spvasm.expected.spvasm @@ -0,0 +1,21 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 10 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %x_10 "x_10" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %uint = OpTypeInt 32 0 +%_ptr_Function_uint = OpTypePointer Function %uint + %8 = OpConstantNull %uint + %main = OpFunction %void None %1 + %4 = OpLabel + %x_10 = OpVariable %_ptr_Function_uint Function %8 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/copy/ptr_copy.spvasm.expected.wgsl b/test/ptr_ref/copy/ptr_copy.spvasm.expected.wgsl new file mode 100644 index 0000000000..ef4c546f29 --- /dev/null +++ b/test/ptr_ref/copy/ptr_copy.spvasm.expected.wgsl @@ -0,0 +1,7 @@ +[[stage(compute)]] +fn main() { + var x_10 : u32; + let x_1 : ptr = &(x_10); + let x_2 : ptr = x_1; + return; +} diff --git a/test/ptr_ref/load/global/i32.spvasm b/test/ptr_ref/load/global/i32.spvasm new file mode 100644 index 0000000000..aace167e9c --- /dev/null +++ b/test/ptr_ref/load/global/i32.spvasm @@ -0,0 +1,19 @@ + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %I "I" + OpName %main "main" + %int = OpTypeInt 32 1 +%_ptr_Private_int = OpTypePointer Private %int + %4 = OpConstantNull %int + %I = OpVariable %_ptr_Private_int Private %4 + %void = OpTypeVoid + %5 = OpTypeFunction %void + %int_1 = OpConstant %int 1 + %main = OpFunction %void None %5 + %8 = OpLabel + %9 = OpLoad %int %I + %11 = OpIAdd %int %9 %int_1 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/global/i32.spvasm.expected.hlsl b/test/ptr_ref/load/global/i32.spvasm.expected.hlsl new file mode 100644 index 0000000000..86cdfa8d64 --- /dev/null +++ b/test/ptr_ref/load/global/i32.spvasm.expected.hlsl @@ -0,0 +1,9 @@ +int I = 0; + +[numthreads(1, 1, 1)] +void main() { + const int x_9 = I; + const int x_11 = (x_9 + 1); + return; +} + diff --git a/test/ptr_ref/load/global/i32.spvasm.expected.msl b/test/ptr_ref/load/global/i32.spvasm.expected.msl new file mode 100644 index 0000000000..1b2d3db8ae --- /dev/null +++ b/test/ptr_ref/load/global/i32.spvasm.expected.msl @@ -0,0 +1 @@ +SKIP: TINT_UNIMPLEMENTED crbug.com/tint/726: module-scope private and workgroup variables not yet implemented diff --git a/test/ptr_ref/load/global/i32.spvasm.expected.spvasm b/test/ptr_ref/load/global/i32.spvasm.expected.spvasm new file mode 100644 index 0000000000..df454002a4 --- /dev/null +++ b/test/ptr_ref/load/global/i32.spvasm.expected.spvasm @@ -0,0 +1,24 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 12 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %I "I" + OpName %main "main" + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 +%_ptr_Private_int = OpTypePointer Private %int + %I = OpVariable %_ptr_Private_int Private %int_0 + %void = OpTypeVoid + %5 = OpTypeFunction %void + %int_1 = OpConstant %int 1 + %main = OpFunction %void None %5 + %8 = OpLabel + %9 = OpLoad %int %I + %11 = OpIAdd %int %9 %int_1 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/global/i32.spvasm.expected.wgsl b/test/ptr_ref/load/global/i32.spvasm.expected.wgsl new file mode 100644 index 0000000000..ba8f551a1b --- /dev/null +++ b/test/ptr_ref/load/global/i32.spvasm.expected.wgsl @@ -0,0 +1,8 @@ +var I : i32 = 0; + +[[stage(compute)]] +fn main() { + let x_9 : i32 = I; + let x_11 : i32 = (x_9 + 1); + return; +} diff --git a/test/ptr_ref/load/global/i32.wgsl b/test/ptr_ref/load/global/i32.wgsl new file mode 100644 index 0000000000..728faf0761 --- /dev/null +++ b/test/ptr_ref/load/global/i32.wgsl @@ -0,0 +1,7 @@ +var I : i32; + +[[stage(compute)]] +fn main() { + let i : i32 = I; + let use : i32 = i + 1; +} diff --git a/test/ptr_ref/load/global/i32.wgsl.expected.hlsl b/test/ptr_ref/load/global/i32.wgsl.expected.hlsl new file mode 100644 index 0000000000..4a6e9e6c08 --- /dev/null +++ b/test/ptr_ref/load/global/i32.wgsl.expected.hlsl @@ -0,0 +1,9 @@ +int I; + +[numthreads(1, 1, 1)] +void main() { + const int i = I; + const int use = (i + 1); + return; +} + diff --git a/test/ptr_ref/load/global/i32.wgsl.expected.msl b/test/ptr_ref/load/global/i32.wgsl.expected.msl new file mode 100644 index 0000000000..1b2d3db8ae --- /dev/null +++ b/test/ptr_ref/load/global/i32.wgsl.expected.msl @@ -0,0 +1 @@ +SKIP: TINT_UNIMPLEMENTED crbug.com/tint/726: module-scope private and workgroup variables not yet implemented diff --git a/test/ptr_ref/load/global/i32.wgsl.expected.spvasm b/test/ptr_ref/load/global/i32.wgsl.expected.spvasm new file mode 100644 index 0000000000..1d701c55d7 --- /dev/null +++ b/test/ptr_ref/load/global/i32.wgsl.expected.spvasm @@ -0,0 +1,24 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 12 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %I "I" + OpName %main "main" + %int = OpTypeInt 32 1 +%_ptr_Private_int = OpTypePointer Private %int + %4 = OpConstantNull %int + %I = OpVariable %_ptr_Private_int Private %4 + %void = OpTypeVoid + %5 = OpTypeFunction %void + %int_1 = OpConstant %int 1 + %main = OpFunction %void None %5 + %8 = OpLabel + %9 = OpLoad %int %I + %11 = OpIAdd %int %9 %int_1 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/global/i32.wgsl.expected.wgsl b/test/ptr_ref/load/global/i32.wgsl.expected.wgsl new file mode 100644 index 0000000000..c656f8e67f --- /dev/null +++ b/test/ptr_ref/load/global/i32.wgsl.expected.wgsl @@ -0,0 +1,7 @@ +var I : i32; + +[[stage(compute)]] +fn main() { + let i : i32 = I; + let use : i32 = (i + 1); +} diff --git a/test/ptr_ref/load/global/struct_field.spvasm b/test/ptr_ref/load/global/struct_field.spvasm new file mode 100644 index 0000000000..149aeae0ed --- /dev/null +++ b/test/ptr_ref/load/global/struct_field.spvasm @@ -0,0 +1,33 @@ + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpSource GLSL 450 + OpName %main "main" + OpName %i "i" + OpName %S "S" + OpMemberName %S 0 "i" + OpName %V "V" + OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize + %void = OpTypeVoid + %3 = OpTypeFunction %void + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %S = OpTypeStruct %int + %_ptr_Private_S = OpTypePointer Private %S + %V = OpVariable %_ptr_Private_S Private + %int_0 = OpConstant %int 0 + %_ptr_Private_int = OpTypePointer Private %int + %uint = OpTypeInt 32 0 + %v3uint = OpTypeVector %uint 3 + %uint_1 = OpConstant %uint 1 + %gl_WorkGroupSize = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1 + %main = OpFunction %void None %3 + %5 = OpLabel + %i = OpVariable %_ptr_Function_int Function + %14 = OpAccessChain %_ptr_Private_int %V %int_0 + %15 = OpLoad %int %14 + OpStore %i %15 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/global/struct_field.spvasm.expected.hlsl b/test/ptr_ref/load/global/struct_field.spvasm.expected.hlsl new file mode 100644 index 0000000000..16f9b25224 --- /dev/null +++ b/test/ptr_ref/load/global/struct_field.spvasm.expected.hlsl @@ -0,0 +1 @@ +SKIP: error: pointers not supported in HLSL diff --git a/test/ptr_ref/load/global/struct_field.spvasm.expected.msl b/test/ptr_ref/load/global/struct_field.spvasm.expected.msl new file mode 100644 index 0000000000..1b2d3db8ae --- /dev/null +++ b/test/ptr_ref/load/global/struct_field.spvasm.expected.msl @@ -0,0 +1 @@ +SKIP: TINT_UNIMPLEMENTED crbug.com/tint/726: module-scope private and workgroup variables not yet implemented diff --git a/test/ptr_ref/load/global/struct_field.spvasm.expected.spvasm b/test/ptr_ref/load/global/struct_field.spvasm.expected.spvasm new file mode 100644 index 0000000000..2a1da682f4 --- /dev/null +++ b/test/ptr_ref/load/global/struct_field.spvasm.expected.spvasm @@ -0,0 +1,35 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 18 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %S "S" + OpMemberName %S 0 "i" + OpName %V "V" + OpName %main "main" + OpName %i "i" + OpMemberDecorate %S 0 Offset 0 + %int = OpTypeInt 32 1 + %S = OpTypeStruct %int +%_ptr_Private_S = OpTypePointer Private %S + %5 = OpConstantNull %S + %V = OpVariable %_ptr_Private_S Private %5 + %void = OpTypeVoid + %6 = OpTypeFunction %void +%_ptr_Function_int = OpTypePointer Function %int + %12 = OpConstantNull %int + %uint = OpTypeInt 32 0 + %uint_0 = OpConstant %uint 0 +%_ptr_Private_int = OpTypePointer Private %int + %main = OpFunction %void None %6 + %9 = OpLabel + %i = OpVariable %_ptr_Function_int Function %12 + %16 = OpAccessChain %_ptr_Private_int %V %uint_0 + %17 = OpLoad %int %16 + OpStore %i %17 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/global/struct_field.spvasm.expected.wgsl b/test/ptr_ref/load/global/struct_field.spvasm.expected.wgsl new file mode 100644 index 0000000000..e3f4540ae2 --- /dev/null +++ b/test/ptr_ref/load/global/struct_field.spvasm.expected.wgsl @@ -0,0 +1,13 @@ +struct S { + i : i32; +}; + +var V : S; + +[[stage(compute)]] +fn main() { + var i : i32; + let x_15 : i32 = V.i; + i = x_15; + return; +} diff --git a/test/ptr_ref/load/global/struct_field.wgsl b/test/ptr_ref/load/global/struct_field.wgsl new file mode 100644 index 0000000000..e35154ba11 --- /dev/null +++ b/test/ptr_ref/load/global/struct_field.wgsl @@ -0,0 +1,10 @@ +struct S { + i : i32; +}; + +var V : S; + +[[stage(compute)]] +fn main() { + let i : i32 = V.i; +} diff --git a/test/ptr_ref/load/global/struct_field.wgsl.expected.hlsl b/test/ptr_ref/load/global/struct_field.wgsl.expected.hlsl new file mode 100644 index 0000000000..80e03bb9c3 --- /dev/null +++ b/test/ptr_ref/load/global/struct_field.wgsl.expected.hlsl @@ -0,0 +1,12 @@ +struct S { + int i; +}; + +S V; + +[numthreads(1, 1, 1)] +void main() { + const int i = V.i; + return; +} + diff --git a/test/ptr_ref/load/global/struct_field.wgsl.expected.msl b/test/ptr_ref/load/global/struct_field.wgsl.expected.msl new file mode 100644 index 0000000000..1b2d3db8ae --- /dev/null +++ b/test/ptr_ref/load/global/struct_field.wgsl.expected.msl @@ -0,0 +1 @@ +SKIP: TINT_UNIMPLEMENTED crbug.com/tint/726: module-scope private and workgroup variables not yet implemented diff --git a/test/ptr_ref/load/global/struct_field.wgsl.expected.spvasm b/test/ptr_ref/load/global/struct_field.wgsl.expected.spvasm new file mode 100644 index 0000000000..471fa58459 --- /dev/null +++ b/test/ptr_ref/load/global/struct_field.wgsl.expected.spvasm @@ -0,0 +1,30 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 15 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %S "S" + OpMemberName %S 0 "i" + OpName %V "V" + OpName %main "main" + OpMemberDecorate %S 0 Offset 0 + %int = OpTypeInt 32 1 + %S = OpTypeStruct %int +%_ptr_Private_S = OpTypePointer Private %S + %5 = OpConstantNull %S + %V = OpVariable %_ptr_Private_S Private %5 + %void = OpTypeVoid + %6 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %uint_0 = OpConstant %uint 0 +%_ptr_Private_int = OpTypePointer Private %int + %main = OpFunction %void None %6 + %9 = OpLabel + %13 = OpAccessChain %_ptr_Private_int %V %uint_0 + %14 = OpLoad %int %13 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/global/struct_field.wgsl.expected.wgsl b/test/ptr_ref/load/global/struct_field.wgsl.expected.wgsl new file mode 100644 index 0000000000..e35154ba11 --- /dev/null +++ b/test/ptr_ref/load/global/struct_field.wgsl.expected.wgsl @@ -0,0 +1,10 @@ +struct S { + i : i32; +}; + +var V : S; + +[[stage(compute)]] +fn main() { + let i : i32 = V.i; +} diff --git a/test/ptr_ref/load/local/i32.spvasm b/test/ptr_ref/load/local/i32.spvasm new file mode 100644 index 0000000000..c44fdd05c6 --- /dev/null +++ b/test/ptr_ref/load/local/i32.spvasm @@ -0,0 +1,26 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 13 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %i "i" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %int_123 = OpConstant %int 123 +%_ptr_Function_int = OpTypePointer Function %int + %9 = OpConstantNull %int + %int_1 = OpConstant %int 1 + %main = OpFunction %void None %1 + %4 = OpLabel + %i = OpVariable %_ptr_Function_int Function %9 + OpStore %i %int_123 + %10 = OpLoad %int %i + %12 = OpIAdd %int %10 %int_1 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/local/i32.spvasm.expected.hlsl b/test/ptr_ref/load/local/i32.spvasm.expected.hlsl new file mode 100644 index 0000000000..6a1180f00f --- /dev/null +++ b/test/ptr_ref/load/local/i32.spvasm.expected.hlsl @@ -0,0 +1,9 @@ +[numthreads(1, 1, 1)] +void main() { + int i = 0; + i = 123; + const int x_10 = i; + const int x_12 = (x_10 + 1); + return; +} + diff --git a/test/ptr_ref/load/local/i32.spvasm.expected.msl b/test/ptr_ref/load/local/i32.spvasm.expected.msl new file mode 100644 index 0000000000..738dfeacc7 --- /dev/null +++ b/test/ptr_ref/load/local/i32.spvasm.expected.msl @@ -0,0 +1,11 @@ +#include + +using namespace metal; +kernel void tint_symbol() { + int i = 0; + i = 123; + int const x_10 = i; + int const x_12 = (x_10 + 1); + return; +} + diff --git a/test/ptr_ref/load/local/i32.spvasm.expected.spvasm b/test/ptr_ref/load/local/i32.spvasm.expected.spvasm new file mode 100644 index 0000000000..bc6f46793c --- /dev/null +++ b/test/ptr_ref/load/local/i32.spvasm.expected.spvasm @@ -0,0 +1,28 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 14 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %i "i" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 +%_ptr_Function_int = OpTypePointer Function %int + %9 = OpConstantNull %int + %int_123 = OpConstant %int 123 + %int_1 = OpConstant %int 1 + %main = OpFunction %void None %1 + %4 = OpLabel + %i = OpVariable %_ptr_Function_int Function %9 + OpStore %i %int_0 + OpStore %i %int_123 + %11 = OpLoad %int %i + %13 = OpIAdd %int %11 %int_1 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/local/i32.spvasm.expected.wgsl b/test/ptr_ref/load/local/i32.spvasm.expected.wgsl new file mode 100644 index 0000000000..60551cdf9a --- /dev/null +++ b/test/ptr_ref/load/local/i32.spvasm.expected.wgsl @@ -0,0 +1,8 @@ +[[stage(compute)]] +fn main() { + var i : i32 = 0; + i = 123; + let x_10 : i32 = i; + let x_12 : i32 = (x_10 + 1); + return; +} diff --git a/test/ptr_ref/load/local/i32.wgsl b/test/ptr_ref/load/local/i32.wgsl new file mode 100644 index 0000000000..1890fd4986 --- /dev/null +++ b/test/ptr_ref/load/local/i32.wgsl @@ -0,0 +1,5 @@ +[[stage(compute)]] +fn main() { + var i : i32 = 123; + let use : i32 = i + 1; +} diff --git a/test/ptr_ref/load/local/i32.wgsl.expected.hlsl b/test/ptr_ref/load/local/i32.wgsl.expected.hlsl new file mode 100644 index 0000000000..fd572806fc --- /dev/null +++ b/test/ptr_ref/load/local/i32.wgsl.expected.hlsl @@ -0,0 +1,7 @@ +[numthreads(1, 1, 1)] +void main() { + int i = 123; + const int use = (i + 1); + return; +} + diff --git a/test/ptr_ref/load/local/i32.wgsl.expected.msl b/test/ptr_ref/load/local/i32.wgsl.expected.msl new file mode 100644 index 0000000000..e7b87bb817 --- /dev/null +++ b/test/ptr_ref/load/local/i32.wgsl.expected.msl @@ -0,0 +1,9 @@ +#include + +using namespace metal; +kernel void tint_symbol() { + int i = 123; + int const use = (i + 1); + return; +} + diff --git a/test/ptr_ref/load/local/i32.wgsl.expected.spvasm b/test/ptr_ref/load/local/i32.wgsl.expected.spvasm new file mode 100644 index 0000000000..c44fdd05c6 --- /dev/null +++ b/test/ptr_ref/load/local/i32.wgsl.expected.spvasm @@ -0,0 +1,26 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 13 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %i "i" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %int_123 = OpConstant %int 123 +%_ptr_Function_int = OpTypePointer Function %int + %9 = OpConstantNull %int + %int_1 = OpConstant %int 1 + %main = OpFunction %void None %1 + %4 = OpLabel + %i = OpVariable %_ptr_Function_int Function %9 + OpStore %i %int_123 + %10 = OpLoad %int %i + %12 = OpIAdd %int %10 %int_1 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/local/i32.wgsl.expected.wgsl b/test/ptr_ref/load/local/i32.wgsl.expected.wgsl new file mode 100644 index 0000000000..e15d6e02f1 --- /dev/null +++ b/test/ptr_ref/load/local/i32.wgsl.expected.wgsl @@ -0,0 +1,5 @@ +[[stage(compute)]] +fn main() { + var i : i32 = 123; + let use : i32 = (i + 1); +} diff --git a/test/ptr_ref/load/local/struct_field.spvasm b/test/ptr_ref/load/local/struct_field.spvasm new file mode 100644 index 0000000000..fa124c5905 --- /dev/null +++ b/test/ptr_ref/load/local/struct_field.spvasm @@ -0,0 +1,32 @@ + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpSource GLSL 450 + OpName %main "main" + OpName %i "i" + OpName %S "S" + OpMemberName %S 0 "i" + OpName %V "V" + OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize + %void = OpTypeVoid + %3 = OpTypeFunction %void + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %S = OpTypeStruct %int + %_ptr_Function_S = OpTypePointer Function %S + %int_0 = OpConstant %int 0 + %uint = OpTypeInt 32 0 + %v3uint = OpTypeVector %uint 3 + %uint_1 = OpConstant %uint 1 + %gl_WorkGroupSize = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1 + %main = OpFunction %void None %3 + %5 = OpLabel + %i = OpVariable %_ptr_Function_int Function + %V = OpVariable %_ptr_Function_S Function + %13 = OpAccessChain %_ptr_Function_int %V %int_0 + %14 = OpLoad %int %13 + OpStore %i %14 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/local/struct_field.spvasm.expected.hlsl b/test/ptr_ref/load/local/struct_field.spvasm.expected.hlsl new file mode 100644 index 0000000000..342340a89b --- /dev/null +++ b/test/ptr_ref/load/local/struct_field.spvasm.expected.hlsl @@ -0,0 +1,13 @@ +struct S { + int i; +}; + +[numthreads(1, 1, 1)] +void main() { + int i = 0; + S V = {0}; + const int x_14 = V.i; + i = x_14; + return; +} + diff --git a/test/ptr_ref/load/local/struct_field.spvasm.expected.msl b/test/ptr_ref/load/local/struct_field.spvasm.expected.msl new file mode 100644 index 0000000000..185bd720cb --- /dev/null +++ b/test/ptr_ref/load/local/struct_field.spvasm.expected.msl @@ -0,0 +1,15 @@ +#include + +using namespace metal; +struct S { + int i; +}; + +kernel void tint_symbol() { + int i = 0; + S V = {}; + int const x_14 = V.i; + i = x_14; + return; +} + diff --git a/test/ptr_ref/load/local/struct_field.spvasm.expected.spvasm b/test/ptr_ref/load/local/struct_field.spvasm.expected.spvasm new file mode 100644 index 0000000000..814dd1b693 --- /dev/null +++ b/test/ptr_ref/load/local/struct_field.spvasm.expected.spvasm @@ -0,0 +1,34 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 17 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %i "i" + OpName %S "S" + OpMemberName %S 0 "i" + OpName %V "V" + OpMemberDecorate %S 0 Offset 0 + %void = OpTypeVoid + %1 = OpTypeFunction %void + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %8 = OpConstantNull %int + %S = OpTypeStruct %int +%_ptr_Function_S = OpTypePointer Function %S + %12 = OpConstantNull %S + %uint = OpTypeInt 32 0 + %uint_0 = OpConstant %uint 0 + %main = OpFunction %void None %1 + %4 = OpLabel + %i = OpVariable %_ptr_Function_int Function %8 + %V = OpVariable %_ptr_Function_S Function %12 + %15 = OpAccessChain %_ptr_Function_int %V %uint_0 + %16 = OpLoad %int %15 + OpStore %i %16 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/local/struct_field.spvasm.expected.wgsl b/test/ptr_ref/load/local/struct_field.spvasm.expected.wgsl new file mode 100644 index 0000000000..ae1c95e7ba --- /dev/null +++ b/test/ptr_ref/load/local/struct_field.spvasm.expected.wgsl @@ -0,0 +1,12 @@ +struct S { + i : i32; +}; + +[[stage(compute)]] +fn main() { + var i : i32; + var V : S; + let x_14 : i32 = V.i; + i = x_14; + return; +} diff --git a/test/ptr_ref/load/local/struct_field.wgsl b/test/ptr_ref/load/local/struct_field.wgsl new file mode 100644 index 0000000000..2242ebbc8c --- /dev/null +++ b/test/ptr_ref/load/local/struct_field.wgsl @@ -0,0 +1,10 @@ +struct S { + i : i32; +}; + +[[stage(compute)]] +fn main() { + var V : S; + var i : i32 = V.i; + return; +} diff --git a/test/ptr_ref/load/local/struct_field.wgsl.expected.hlsl b/test/ptr_ref/load/local/struct_field.wgsl.expected.hlsl new file mode 100644 index 0000000000..efe9eb6c3b --- /dev/null +++ b/test/ptr_ref/load/local/struct_field.wgsl.expected.hlsl @@ -0,0 +1,11 @@ +struct S { + int i; +}; + +[numthreads(1, 1, 1)] +void main() { + S V = {0}; + int i = V.i; + return; +} + diff --git a/test/ptr_ref/load/local/struct_field.wgsl.expected.msl b/test/ptr_ref/load/local/struct_field.wgsl.expected.msl new file mode 100644 index 0000000000..e6c6fb2c9c --- /dev/null +++ b/test/ptr_ref/load/local/struct_field.wgsl.expected.msl @@ -0,0 +1,13 @@ +#include + +using namespace metal; +struct S { + int i; +}; + +kernel void tint_symbol() { + S V = {}; + int i = V.i; + return; +} + diff --git a/test/ptr_ref/load/local/struct_field.wgsl.expected.spvasm b/test/ptr_ref/load/local/struct_field.wgsl.expected.spvasm new file mode 100644 index 0000000000..52c8d560e6 --- /dev/null +++ b/test/ptr_ref/load/local/struct_field.wgsl.expected.spvasm @@ -0,0 +1,34 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 17 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %S "S" + OpMemberName %S 0 "i" + OpName %V "V" + OpName %i "i" + OpMemberDecorate %S 0 Offset 0 + %void = OpTypeVoid + %1 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %S = OpTypeStruct %int +%_ptr_Function_S = OpTypePointer Function %S + %9 = OpConstantNull %S + %uint = OpTypeInt 32 0 + %uint_0 = OpConstant %uint 0 +%_ptr_Function_int = OpTypePointer Function %int + %16 = OpConstantNull %int + %main = OpFunction %void None %1 + %4 = OpLabel + %V = OpVariable %_ptr_Function_S Function %9 + %i = OpVariable %_ptr_Function_int Function %16 + %13 = OpAccessChain %_ptr_Function_int %V %uint_0 + %14 = OpLoad %int %13 + OpStore %i %14 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/local/struct_field.wgsl.expected.wgsl b/test/ptr_ref/load/local/struct_field.wgsl.expected.wgsl new file mode 100644 index 0000000000..2242ebbc8c --- /dev/null +++ b/test/ptr_ref/load/local/struct_field.wgsl.expected.wgsl @@ -0,0 +1,10 @@ +struct S { + i : i32; +}; + +[[stage(compute)]] +fn main() { + var V : S; + var i : i32 = V.i; + return; +} diff --git a/test/ptr_ref/load/param/ptr.spvasm b/test/ptr_ref/load/param/ptr.spvasm new file mode 100644 index 0000000000..bf904d14de --- /dev/null +++ b/test/ptr_ref/load/param/ptr.spvasm @@ -0,0 +1,37 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 21 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %func "func" + OpName %value "value" + OpName %pointer "pointer" + OpName %main "main" + OpName %i "i" + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %1 = OpTypeFunction %int %int %_ptr_Function_int + %void = OpTypeVoid + %11 = OpTypeFunction %void + %int_123 = OpConstant %int 123 + %17 = OpConstantNull %int + %func = OpFunction %int None %1 + %value = OpFunctionParameter %int + %pointer = OpFunctionParameter %_ptr_Function_int + %7 = OpLabel + %9 = OpLoad %int %pointer + %10 = OpIAdd %int %value %9 + OpReturnValue %10 + OpFunctionEnd + %main = OpFunction %void None %11 + %14 = OpLabel + %i = OpVariable %_ptr_Function_int Function %17 + OpStore %i %int_123 + %19 = OpLoad %int %i + %18 = OpFunctionCall %int %func %19 %i + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/param/ptr.spvasm.expected.hlsl b/test/ptr_ref/load/param/ptr.spvasm.expected.hlsl new file mode 100644 index 0000000000..16f9b25224 --- /dev/null +++ b/test/ptr_ref/load/param/ptr.spvasm.expected.hlsl @@ -0,0 +1 @@ +SKIP: error: pointers not supported in HLSL diff --git a/test/ptr_ref/load/param/ptr.spvasm.expected.msl b/test/ptr_ref/load/param/ptr.spvasm.expected.msl new file mode 100644 index 0000000000..cbe0a55a64 --- /dev/null +++ b/test/ptr_ref/load/param/ptr.spvasm.expected.msl @@ -0,0 +1,16 @@ +#include + +using namespace metal; +int func(int value, int* pointer) { + int const x_9 = *(pointer); + return (value + x_9); +} + +kernel void tint_symbol() { + int i = 0; + i = 123; + int const x_19 = i; + int const x_18 = func(x_19, &(i)); + return; +} + diff --git a/test/ptr_ref/load/param/ptr.spvasm.expected.spvasm b/test/ptr_ref/load/param/ptr.spvasm.expected.spvasm new file mode 100644 index 0000000000..967e2a68d4 --- /dev/null +++ b/test/ptr_ref/load/param/ptr.spvasm.expected.spvasm @@ -0,0 +1,39 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 22 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %func "func" + OpName %value "value" + OpName %pointer "pointer" + OpName %main "main" + OpName %i "i" + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %1 = OpTypeFunction %int %int %_ptr_Function_int + %void = OpTypeVoid + %11 = OpTypeFunction %void + %int_0 = OpConstant %int 0 + %17 = OpConstantNull %int + %int_123 = OpConstant %int 123 + %func = OpFunction %int None %1 + %value = OpFunctionParameter %int + %pointer = OpFunctionParameter %_ptr_Function_int + %7 = OpLabel + %9 = OpLoad %int %pointer + %10 = OpIAdd %int %value %9 + OpReturnValue %10 + OpFunctionEnd + %main = OpFunction %void None %11 + %14 = OpLabel + %i = OpVariable %_ptr_Function_int Function %17 + OpStore %i %int_0 + OpStore %i %int_123 + %19 = OpLoad %int %i + %20 = OpFunctionCall %int %func %19 %i + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/param/ptr.spvasm.expected.wgsl b/test/ptr_ref/load/param/ptr.spvasm.expected.wgsl new file mode 100644 index 0000000000..e74bd4e7db --- /dev/null +++ b/test/ptr_ref/load/param/ptr.spvasm.expected.wgsl @@ -0,0 +1,13 @@ +fn func(value : i32, pointer : ptr) -> i32 { + let x_9 : i32 = *(pointer); + return (value + x_9); +} + +[[stage(compute)]] +fn main() { + var i : i32 = 0; + i = 123; + let x_19 : i32 = i; + let x_18 : i32 = func(x_19, &(i)); + return; +} diff --git a/test/ptr_ref/load/param/ptr.wgsl b/test/ptr_ref/load/param/ptr.wgsl new file mode 100644 index 0000000000..d57e057d79 --- /dev/null +++ b/test/ptr_ref/load/param/ptr.wgsl @@ -0,0 +1,9 @@ +fn func(value : i32, pointer : ptr) -> i32 { + return value + *pointer; +} + +[[stage(compute)]] +fn main() { + var i : i32 = 123; + let r : i32 = func(i, &i); +} diff --git a/test/ptr_ref/load/param/ptr.wgsl.expected.hlsl b/test/ptr_ref/load/param/ptr.wgsl.expected.hlsl new file mode 100644 index 0000000000..16f9b25224 --- /dev/null +++ b/test/ptr_ref/load/param/ptr.wgsl.expected.hlsl @@ -0,0 +1 @@ +SKIP: error: pointers not supported in HLSL diff --git a/test/ptr_ref/load/param/ptr.wgsl.expected.msl b/test/ptr_ref/load/param/ptr.wgsl.expected.msl new file mode 100644 index 0000000000..48556e1555 --- /dev/null +++ b/test/ptr_ref/load/param/ptr.wgsl.expected.msl @@ -0,0 +1,13 @@ +#include + +using namespace metal; +int func(int value, int* pointer) { + return (value + *(pointer)); +} + +kernel void tint_symbol() { + int i = 123; + int const r = func(i, &(i)); + return; +} + diff --git a/test/ptr_ref/load/param/ptr.wgsl.expected.spvasm b/test/ptr_ref/load/param/ptr.wgsl.expected.spvasm new file mode 100644 index 0000000000..bf904d14de --- /dev/null +++ b/test/ptr_ref/load/param/ptr.wgsl.expected.spvasm @@ -0,0 +1,37 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 21 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %func "func" + OpName %value "value" + OpName %pointer "pointer" + OpName %main "main" + OpName %i "i" + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %1 = OpTypeFunction %int %int %_ptr_Function_int + %void = OpTypeVoid + %11 = OpTypeFunction %void + %int_123 = OpConstant %int 123 + %17 = OpConstantNull %int + %func = OpFunction %int None %1 + %value = OpFunctionParameter %int + %pointer = OpFunctionParameter %_ptr_Function_int + %7 = OpLabel + %9 = OpLoad %int %pointer + %10 = OpIAdd %int %value %9 + OpReturnValue %10 + OpFunctionEnd + %main = OpFunction %void None %11 + %14 = OpLabel + %i = OpVariable %_ptr_Function_int Function %17 + OpStore %i %int_123 + %19 = OpLoad %int %i + %18 = OpFunctionCall %int %func %19 %i + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/load/param/ptr.wgsl.expected.wgsl b/test/ptr_ref/load/param/ptr.wgsl.expected.wgsl new file mode 100644 index 0000000000..bcfc824fb5 --- /dev/null +++ b/test/ptr_ref/load/param/ptr.wgsl.expected.wgsl @@ -0,0 +1,9 @@ +fn func(value : i32, pointer : ptr) -> i32 { + return (value + *(pointer)); +} + +[[stage(compute)]] +fn main() { + var i : i32 = 123; + let r : i32 = func(i, &(i)); +} diff --git a/test/ptr_ref/store/global/i32.spvasm b/test/ptr_ref/store/global/i32.spvasm new file mode 100644 index 0000000000..8c25a15a92 --- /dev/null +++ b/test/ptr_ref/store/global/i32.spvasm @@ -0,0 +1,29 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 15 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %I "I" + OpName %main "main" + %int = OpTypeInt 32 1 +%_ptr_Private_int = OpTypePointer Private %int + %4 = OpConstantNull %int + %I = OpVariable %_ptr_Private_int Private %4 + %void = OpTypeVoid + %5 = OpTypeFunction %void + %int_123 = OpConstant %int 123 + %int_100 = OpConstant %int 100 + %int_20 = OpConstant %int 20 + %int_3 = OpConstant %int 3 + %main = OpFunction %void None %5 + %8 = OpLabel + OpStore %I %int_123 + %12 = OpIAdd %int %int_100 %int_20 + %14 = OpIAdd %int %12 %int_3 + OpStore %I %14 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/global/i32.spvasm.expected.hlsl b/test/ptr_ref/store/global/i32.spvasm.expected.hlsl new file mode 100644 index 0000000000..104200bb03 --- /dev/null +++ b/test/ptr_ref/store/global/i32.spvasm.expected.hlsl @@ -0,0 +1,9 @@ +int I = 0; + +[numthreads(1, 1, 1)] +void main() { + I = 123; + I = ((100 + 20) + 3); + return; +} + diff --git a/test/ptr_ref/store/global/i32.spvasm.expected.msl b/test/ptr_ref/store/global/i32.spvasm.expected.msl new file mode 100644 index 0000000000..1b2d3db8ae --- /dev/null +++ b/test/ptr_ref/store/global/i32.spvasm.expected.msl @@ -0,0 +1 @@ +SKIP: TINT_UNIMPLEMENTED crbug.com/tint/726: module-scope private and workgroup variables not yet implemented diff --git a/test/ptr_ref/store/global/i32.spvasm.expected.spvasm b/test/ptr_ref/store/global/i32.spvasm.expected.spvasm new file mode 100644 index 0000000000..786fc8a232 --- /dev/null +++ b/test/ptr_ref/store/global/i32.spvasm.expected.spvasm @@ -0,0 +1,29 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 15 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %I "I" + OpName %main "main" + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 +%_ptr_Private_int = OpTypePointer Private %int + %I = OpVariable %_ptr_Private_int Private %int_0 + %void = OpTypeVoid + %5 = OpTypeFunction %void + %int_123 = OpConstant %int 123 + %int_100 = OpConstant %int 100 + %int_20 = OpConstant %int 20 + %int_3 = OpConstant %int 3 + %main = OpFunction %void None %5 + %8 = OpLabel + OpStore %I %int_123 + %12 = OpIAdd %int %int_100 %int_20 + %14 = OpIAdd %int %12 %int_3 + OpStore %I %14 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/global/i32.spvasm.expected.wgsl b/test/ptr_ref/store/global/i32.spvasm.expected.wgsl new file mode 100644 index 0000000000..9d7722f2a0 --- /dev/null +++ b/test/ptr_ref/store/global/i32.spvasm.expected.wgsl @@ -0,0 +1,8 @@ +var I : i32 = 0; + +[[stage(compute)]] +fn main() { + I = 123; + I = ((100 + 20) + 3); + return; +} diff --git a/test/ptr_ref/store/global/i32.wgsl b/test/ptr_ref/store/global/i32.wgsl new file mode 100644 index 0000000000..009f457ff2 --- /dev/null +++ b/test/ptr_ref/store/global/i32.wgsl @@ -0,0 +1,7 @@ +var I : i32; + +[[stage(compute)]] +fn main() { + I = 123; // constant + I = 100 + 20 + 3; // dynamic +} diff --git a/test/ptr_ref/store/global/i32.wgsl.expected.hlsl b/test/ptr_ref/store/global/i32.wgsl.expected.hlsl new file mode 100644 index 0000000000..44c165449c --- /dev/null +++ b/test/ptr_ref/store/global/i32.wgsl.expected.hlsl @@ -0,0 +1,9 @@ +int I; + +[numthreads(1, 1, 1)] +void main() { + I = 123; + I = ((100 + 20) + 3); + return; +} + diff --git a/test/ptr_ref/store/global/i32.wgsl.expected.msl b/test/ptr_ref/store/global/i32.wgsl.expected.msl new file mode 100644 index 0000000000..1b2d3db8ae --- /dev/null +++ b/test/ptr_ref/store/global/i32.wgsl.expected.msl @@ -0,0 +1 @@ +SKIP: TINT_UNIMPLEMENTED crbug.com/tint/726: module-scope private and workgroup variables not yet implemented diff --git a/test/ptr_ref/store/global/i32.wgsl.expected.spvasm b/test/ptr_ref/store/global/i32.wgsl.expected.spvasm new file mode 100644 index 0000000000..8c25a15a92 --- /dev/null +++ b/test/ptr_ref/store/global/i32.wgsl.expected.spvasm @@ -0,0 +1,29 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 15 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %I "I" + OpName %main "main" + %int = OpTypeInt 32 1 +%_ptr_Private_int = OpTypePointer Private %int + %4 = OpConstantNull %int + %I = OpVariable %_ptr_Private_int Private %4 + %void = OpTypeVoid + %5 = OpTypeFunction %void + %int_123 = OpConstant %int 123 + %int_100 = OpConstant %int 100 + %int_20 = OpConstant %int 20 + %int_3 = OpConstant %int 3 + %main = OpFunction %void None %5 + %8 = OpLabel + OpStore %I %int_123 + %12 = OpIAdd %int %int_100 %int_20 + %14 = OpIAdd %int %12 %int_3 + OpStore %I %14 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/global/i32.wgsl.expected.wgsl b/test/ptr_ref/store/global/i32.wgsl.expected.wgsl new file mode 100644 index 0000000000..b9959900fd --- /dev/null +++ b/test/ptr_ref/store/global/i32.wgsl.expected.wgsl @@ -0,0 +1,7 @@ +var I : i32; + +[[stage(compute)]] +fn main() { + I = 123; + I = ((100 + 20) + 3); +} diff --git a/test/ptr_ref/store/global/struct_field.spvasm b/test/ptr_ref/store/global/struct_field.spvasm new file mode 100644 index 0000000000..b3ca86be6b --- /dev/null +++ b/test/ptr_ref/store/global/struct_field.spvasm @@ -0,0 +1,30 @@ + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpSource GLSL 450 + OpName %main "main" + OpName %S "S" + OpMemberName %S 0 "i" + OpName %V "V" + OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize + %void = OpTypeVoid + %3 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %S = OpTypeStruct %int + %_ptr_Private_S = OpTypePointer Private %S + %V = OpVariable %_ptr_Private_S Private + %int_0 = OpConstant %int 0 + %int_5 = OpConstant %int 5 +%_ptr_Private_int = OpTypePointer Private %int + %uint = OpTypeInt 32 0 + %v3uint = OpTypeVector %uint 3 + %uint_1 = OpConstant %uint 1 +%gl_WorkGroupSize = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1 + %main = OpFunction %void None %3 + %5 = OpLabel + %13 = OpAccessChain %_ptr_Private_int %V %int_0 + OpStore %13 %int_5 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/global/struct_field.spvasm.expected.hlsl b/test/ptr_ref/store/global/struct_field.spvasm.expected.hlsl new file mode 100644 index 0000000000..16f9b25224 --- /dev/null +++ b/test/ptr_ref/store/global/struct_field.spvasm.expected.hlsl @@ -0,0 +1 @@ +SKIP: error: pointers not supported in HLSL diff --git a/test/ptr_ref/store/global/struct_field.spvasm.expected.msl b/test/ptr_ref/store/global/struct_field.spvasm.expected.msl new file mode 100644 index 0000000000..1b2d3db8ae --- /dev/null +++ b/test/ptr_ref/store/global/struct_field.spvasm.expected.msl @@ -0,0 +1 @@ +SKIP: TINT_UNIMPLEMENTED crbug.com/tint/726: module-scope private and workgroup variables not yet implemented diff --git a/test/ptr_ref/store/global/struct_field.spvasm.expected.spvasm b/test/ptr_ref/store/global/struct_field.spvasm.expected.spvasm new file mode 100644 index 0000000000..e63c070c44 --- /dev/null +++ b/test/ptr_ref/store/global/struct_field.spvasm.expected.spvasm @@ -0,0 +1,31 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 15 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %S "S" + OpMemberName %S 0 "i" + OpName %V "V" + OpName %main "main" + OpMemberDecorate %S 0 Offset 0 + %int = OpTypeInt 32 1 + %S = OpTypeStruct %int +%_ptr_Private_S = OpTypePointer Private %S + %5 = OpConstantNull %S + %V = OpVariable %_ptr_Private_S Private %5 + %void = OpTypeVoid + %6 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %uint_0 = OpConstant %uint 0 +%_ptr_Private_int = OpTypePointer Private %int + %int_5 = OpConstant %int 5 + %main = OpFunction %void None %6 + %9 = OpLabel + %13 = OpAccessChain %_ptr_Private_int %V %uint_0 + OpStore %13 %int_5 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/global/struct_field.spvasm.expected.wgsl b/test/ptr_ref/store/global/struct_field.spvasm.expected.wgsl new file mode 100644 index 0000000000..50cb6f400a --- /dev/null +++ b/test/ptr_ref/store/global/struct_field.spvasm.expected.wgsl @@ -0,0 +1,11 @@ +struct S { + i : i32; +}; + +var V : S; + +[[stage(compute)]] +fn main() { + V.i = 5; + return; +} diff --git a/test/ptr_ref/store/local/i32.spvasm b/test/ptr_ref/store/local/i32.spvasm new file mode 100644 index 0000000000..30df9e1039 --- /dev/null +++ b/test/ptr_ref/store/local/i32.spvasm @@ -0,0 +1,30 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 18 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %i "i" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %int_123 = OpConstant %int 123 +%_ptr_Function_int = OpTypePointer Function %int + %9 = OpConstantNull %int + %int_100 = OpConstant %int 100 + %int_20 = OpConstant %int 20 + %int_3 = OpConstant %int 3 + %main = OpFunction %void None %1 + %4 = OpLabel + %i = OpVariable %_ptr_Function_int Function %9 + OpStore %i %int_123 + OpStore %i %int_123 + %15 = OpIAdd %int %int_100 %int_20 + %17 = OpIAdd %int %15 %int_3 + OpStore %i %17 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/local/i32.spvasm.expected.hlsl b/test/ptr_ref/store/local/i32.spvasm.expected.hlsl new file mode 100644 index 0000000000..c6dc7c541c --- /dev/null +++ b/test/ptr_ref/store/local/i32.spvasm.expected.hlsl @@ -0,0 +1,9 @@ +[numthreads(1, 1, 1)] +void main() { + int i = 0; + i = 123; + i = 123; + i = ((100 + 20) + 3); + return; +} + diff --git a/test/ptr_ref/store/local/i32.spvasm.expected.msl b/test/ptr_ref/store/local/i32.spvasm.expected.msl new file mode 100644 index 0000000000..21174ae8cf --- /dev/null +++ b/test/ptr_ref/store/local/i32.spvasm.expected.msl @@ -0,0 +1,11 @@ +#include + +using namespace metal; +kernel void tint_symbol() { + int i = 0; + i = 123; + i = 123; + i = ((100 + 20) + 3); + return; +} + diff --git a/test/ptr_ref/store/local/i32.spvasm.expected.spvasm b/test/ptr_ref/store/local/i32.spvasm.expected.spvasm new file mode 100644 index 0000000000..5a05b5ef88 --- /dev/null +++ b/test/ptr_ref/store/local/i32.spvasm.expected.spvasm @@ -0,0 +1,32 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 16 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %i "i" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 +%_ptr_Function_int = OpTypePointer Function %int + %9 = OpConstantNull %int + %int_123 = OpConstant %int 123 + %int_100 = OpConstant %int 100 + %int_20 = OpConstant %int 20 + %int_3 = OpConstant %int 3 + %main = OpFunction %void None %1 + %4 = OpLabel + %i = OpVariable %_ptr_Function_int Function %9 + OpStore %i %int_0 + OpStore %i %int_123 + OpStore %i %int_123 + %13 = OpIAdd %int %int_100 %int_20 + %15 = OpIAdd %int %13 %int_3 + OpStore %i %15 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/local/i32.spvasm.expected.wgsl b/test/ptr_ref/store/local/i32.spvasm.expected.wgsl new file mode 100644 index 0000000000..ebc870ac4f --- /dev/null +++ b/test/ptr_ref/store/local/i32.spvasm.expected.wgsl @@ -0,0 +1,8 @@ +[[stage(compute)]] +fn main() { + var i : i32 = 0; + i = 123; + i = 123; + i = ((100 + 20) + 3); + return; +} diff --git a/test/ptr_ref/store/local/i32.wgsl b/test/ptr_ref/store/local/i32.wgsl new file mode 100644 index 0000000000..ccfe0d6d28 --- /dev/null +++ b/test/ptr_ref/store/local/i32.wgsl @@ -0,0 +1,7 @@ +[[stage(compute)]] +fn main() { + var i : i32 = 123; + let p : ptr = &i; + *p = 123; // constant + *p = 100 + 20 + 3; // dynamic +} diff --git a/test/ptr_ref/store/local/i32.wgsl.expected.hlsl b/test/ptr_ref/store/local/i32.wgsl.expected.hlsl new file mode 100644 index 0000000000..16f9b25224 --- /dev/null +++ b/test/ptr_ref/store/local/i32.wgsl.expected.hlsl @@ -0,0 +1 @@ +SKIP: error: pointers not supported in HLSL diff --git a/test/ptr_ref/store/local/i32.wgsl.expected.msl b/test/ptr_ref/store/local/i32.wgsl.expected.msl new file mode 100644 index 0000000000..6674f82ca9 --- /dev/null +++ b/test/ptr_ref/store/local/i32.wgsl.expected.msl @@ -0,0 +1,11 @@ +#include + +using namespace metal; +kernel void tint_symbol() { + int i = 123; + int* const p = &(i); + *(p) = 123; + *(p) = ((100 + 20) + 3); + return; +} + diff --git a/test/ptr_ref/store/local/i32.wgsl.expected.spvasm b/test/ptr_ref/store/local/i32.wgsl.expected.spvasm new file mode 100644 index 0000000000..30df9e1039 --- /dev/null +++ b/test/ptr_ref/store/local/i32.wgsl.expected.spvasm @@ -0,0 +1,30 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 18 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %i "i" + %void = OpTypeVoid + %1 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %int_123 = OpConstant %int 123 +%_ptr_Function_int = OpTypePointer Function %int + %9 = OpConstantNull %int + %int_100 = OpConstant %int 100 + %int_20 = OpConstant %int 20 + %int_3 = OpConstant %int 3 + %main = OpFunction %void None %1 + %4 = OpLabel + %i = OpVariable %_ptr_Function_int Function %9 + OpStore %i %int_123 + OpStore %i %int_123 + %15 = OpIAdd %int %int_100 %int_20 + %17 = OpIAdd %int %15 %int_3 + OpStore %i %17 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/local/i32.wgsl.expected.wgsl b/test/ptr_ref/store/local/i32.wgsl.expected.wgsl new file mode 100644 index 0000000000..36391d6b9f --- /dev/null +++ b/test/ptr_ref/store/local/i32.wgsl.expected.wgsl @@ -0,0 +1,7 @@ +[[stage(compute)]] +fn main() { + var i : i32 = 123; + let p : ptr = &(i); + *(p) = 123; + *(p) = ((100 + 20) + 3); +} diff --git a/test/ptr_ref/store/local/struct_field.spvasm b/test/ptr_ref/store/local/struct_field.spvasm new file mode 100644 index 0000000000..1c850d1b60 --- /dev/null +++ b/test/ptr_ref/store/local/struct_field.spvasm @@ -0,0 +1,30 @@ + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpSource GLSL 450 + OpName %main "main" + OpName %S "S" + OpMemberName %S 0 "i" + OpName %V "V" + OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize + %void = OpTypeVoid + %3 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %S = OpTypeStruct %int + %_ptr_Function_S = OpTypePointer Function %S + %int_0 = OpConstant %int 0 + %int_5 = OpConstant %int 5 +%_ptr_Function_int = OpTypePointer Function %int + %uint = OpTypeInt 32 0 + %v3uint = OpTypeVector %uint 3 + %uint_1 = OpConstant %uint 1 + %gl_WorkGroupSize = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1 + %main = OpFunction %void None %3 + %5 = OpLabel + %V = OpVariable %_ptr_Function_S Function + %13 = OpAccessChain %_ptr_Function_int %V %int_0 + OpStore %13 %int_5 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/local/struct_field.spvasm.expected.hlsl b/test/ptr_ref/store/local/struct_field.spvasm.expected.hlsl new file mode 100644 index 0000000000..247388a94a --- /dev/null +++ b/test/ptr_ref/store/local/struct_field.spvasm.expected.hlsl @@ -0,0 +1,11 @@ +struct S { + int i; +}; + +[numthreads(1, 1, 1)] +void main() { + S V = {0}; + V.i = 5; + return; +} + diff --git a/test/ptr_ref/store/local/struct_field.spvasm.expected.msl b/test/ptr_ref/store/local/struct_field.spvasm.expected.msl new file mode 100644 index 0000000000..2e6989d13e --- /dev/null +++ b/test/ptr_ref/store/local/struct_field.spvasm.expected.msl @@ -0,0 +1,13 @@ +#include + +using namespace metal; +struct S { + int i; +}; + +kernel void tint_symbol() { + S V = {}; + V.i = 5; + return; +} + diff --git a/test/ptr_ref/store/local/struct_field.spvasm.expected.spvasm b/test/ptr_ref/store/local/struct_field.spvasm.expected.spvasm new file mode 100644 index 0000000000..255c691960 --- /dev/null +++ b/test/ptr_ref/store/local/struct_field.spvasm.expected.spvasm @@ -0,0 +1,31 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 15 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %main "main" + OpName %S "S" + OpMemberName %S 0 "i" + OpName %V "V" + OpMemberDecorate %S 0 Offset 0 + %void = OpTypeVoid + %1 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %S = OpTypeStruct %int +%_ptr_Function_S = OpTypePointer Function %S + %9 = OpConstantNull %S + %uint = OpTypeInt 32 0 + %uint_0 = OpConstant %uint 0 +%_ptr_Function_int = OpTypePointer Function %int + %int_5 = OpConstant %int 5 + %main = OpFunction %void None %1 + %4 = OpLabel + %V = OpVariable %_ptr_Function_S Function %9 + %13 = OpAccessChain %_ptr_Function_int %V %uint_0 + OpStore %13 %int_5 + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/local/struct_field.spvasm.expected.wgsl b/test/ptr_ref/store/local/struct_field.spvasm.expected.wgsl new file mode 100644 index 0000000000..77d7681d3d --- /dev/null +++ b/test/ptr_ref/store/local/struct_field.spvasm.expected.wgsl @@ -0,0 +1,10 @@ +struct S { + i : i32; +}; + +[[stage(compute)]] +fn main() { + var V : S; + V.i = 5; + return; +} diff --git a/test/ptr_ref/store/param/ptr.spvasm b/test/ptr_ref/store/param/ptr.spvasm new file mode 100644 index 0000000000..e7505382e2 --- /dev/null +++ b/test/ptr_ref/store/param/ptr.spvasm @@ -0,0 +1,35 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 18 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %func "func" + OpName %value "value" + OpName %pointer "pointer" + OpName %main "main" + OpName %i "i" + %void = OpTypeVoid + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %1 = OpTypeFunction %void %int %_ptr_Function_int + %10 = OpTypeFunction %void + %int_123 = OpConstant %int 123 + %15 = OpConstantNull %int + %func = OpFunction %void None %1 + %value = OpFunctionParameter %int + %pointer = OpFunctionParameter %_ptr_Function_int + %8 = OpLabel + OpStore %pointer %value + OpReturn + OpFunctionEnd + %main = OpFunction %void None %10 + %12 = OpLabel + %i = OpVariable %_ptr_Function_int Function %15 + OpStore %i %int_123 + %16 = OpFunctionCall %void %func %int_123 %i + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/param/ptr.spvasm.expected.hlsl b/test/ptr_ref/store/param/ptr.spvasm.expected.hlsl new file mode 100644 index 0000000000..16f9b25224 --- /dev/null +++ b/test/ptr_ref/store/param/ptr.spvasm.expected.hlsl @@ -0,0 +1 @@ +SKIP: error: pointers not supported in HLSL diff --git a/test/ptr_ref/store/param/ptr.spvasm.expected.msl b/test/ptr_ref/store/param/ptr.spvasm.expected.msl new file mode 100644 index 0000000000..5d459da3dd --- /dev/null +++ b/test/ptr_ref/store/param/ptr.spvasm.expected.msl @@ -0,0 +1,15 @@ +#include + +using namespace metal; +void func(int value, int* pointer) { + *(pointer) = value; + return; +} + +kernel void tint_symbol() { + int i = 0; + i = 123; + func(123, &(i)); + return; +} + diff --git a/test/ptr_ref/store/param/ptr.spvasm.expected.spvasm b/test/ptr_ref/store/param/ptr.spvasm.expected.spvasm new file mode 100644 index 0000000000..8126ab6ada --- /dev/null +++ b/test/ptr_ref/store/param/ptr.spvasm.expected.spvasm @@ -0,0 +1,37 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 19 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %func "func" + OpName %value "value" + OpName %pointer "pointer" + OpName %main "main" + OpName %i "i" + %void = OpTypeVoid + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %1 = OpTypeFunction %void %int %_ptr_Function_int + %10 = OpTypeFunction %void + %int_0 = OpConstant %int 0 + %15 = OpConstantNull %int + %int_123 = OpConstant %int 123 + %func = OpFunction %void None %1 + %value = OpFunctionParameter %int + %pointer = OpFunctionParameter %_ptr_Function_int + %8 = OpLabel + OpStore %pointer %value + OpReturn + OpFunctionEnd + %main = OpFunction %void None %10 + %12 = OpLabel + %i = OpVariable %_ptr_Function_int Function %15 + OpStore %i %int_0 + OpStore %i %int_123 + %17 = OpFunctionCall %void %func %int_123 %i + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/param/ptr.spvasm.expected.wgsl b/test/ptr_ref/store/param/ptr.spvasm.expected.wgsl new file mode 100644 index 0000000000..b3de2ebe12 --- /dev/null +++ b/test/ptr_ref/store/param/ptr.spvasm.expected.wgsl @@ -0,0 +1,12 @@ +fn func(value : i32, pointer : ptr) { + *(pointer) = value; + return; +} + +[[stage(compute)]] +fn main() { + var i : i32 = 0; + i = 123; + func(123, &(i)); + return; +} diff --git a/test/ptr_ref/store/param/ptr.wgsl b/test/ptr_ref/store/param/ptr.wgsl new file mode 100644 index 0000000000..6cba3d3364 --- /dev/null +++ b/test/ptr_ref/store/param/ptr.wgsl @@ -0,0 +1,9 @@ +fn func(value : i32, pointer : ptr) { + *pointer = value; +} + +[[stage(compute)]] +fn main() { + var i : i32 = 123; + func(123, &i); +} diff --git a/test/ptr_ref/store/param/ptr.wgsl.expected.hlsl b/test/ptr_ref/store/param/ptr.wgsl.expected.hlsl new file mode 100644 index 0000000000..16f9b25224 --- /dev/null +++ b/test/ptr_ref/store/param/ptr.wgsl.expected.hlsl @@ -0,0 +1 @@ +SKIP: error: pointers not supported in HLSL diff --git a/test/ptr_ref/store/param/ptr.wgsl.expected.msl b/test/ptr_ref/store/param/ptr.wgsl.expected.msl new file mode 100644 index 0000000000..517183a5e8 --- /dev/null +++ b/test/ptr_ref/store/param/ptr.wgsl.expected.msl @@ -0,0 +1,13 @@ +#include + +using namespace metal; +void func(int value, int* pointer) { + *(pointer) = value; +} + +kernel void tint_symbol() { + int i = 123; + func(123, &(i)); + return; +} + diff --git a/test/ptr_ref/store/param/ptr.wgsl.expected.spvasm b/test/ptr_ref/store/param/ptr.wgsl.expected.spvasm new file mode 100644 index 0000000000..e7505382e2 --- /dev/null +++ b/test/ptr_ref/store/param/ptr.wgsl.expected.spvasm @@ -0,0 +1,35 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 18 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %func "func" + OpName %value "value" + OpName %pointer "pointer" + OpName %main "main" + OpName %i "i" + %void = OpTypeVoid + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %1 = OpTypeFunction %void %int %_ptr_Function_int + %10 = OpTypeFunction %void + %int_123 = OpConstant %int 123 + %15 = OpConstantNull %int + %func = OpFunction %void None %1 + %value = OpFunctionParameter %int + %pointer = OpFunctionParameter %_ptr_Function_int + %8 = OpLabel + OpStore %pointer %value + OpReturn + OpFunctionEnd + %main = OpFunction %void None %10 + %12 = OpLabel + %i = OpVariable %_ptr_Function_int Function %15 + OpStore %i %int_123 + %16 = OpFunctionCall %void %func %int_123 %i + OpReturn + OpFunctionEnd diff --git a/test/ptr_ref/store/param/ptr.wgsl.expected.wgsl b/test/ptr_ref/store/param/ptr.wgsl.expected.wgsl new file mode 100644 index 0000000000..78b33921f3 --- /dev/null +++ b/test/ptr_ref/store/param/ptr.wgsl.expected.wgsl @@ -0,0 +1,9 @@ +fn func(value : i32, pointer : ptr) { + *(pointer) = value; +} + +[[stage(compute)]] +fn main() { + var i : i32 = 123; + func(123, &(i)); +} diff --git a/test/samples/compute_boids.wgsl.expected.msl b/test/samples/compute_boids.wgsl.expected.msl index 05afb515d1..8b7f48514e 100644 --- a/test/samples/compute_boids.wgsl.expected.msl +++ b/test/samples/compute_boids.wgsl.expected.msl @@ -33,9 +33,9 @@ struct tint_symbol_5 { }; vertex tint_symbol_2 vert_main(tint_symbol_1 tint_symbol [[stage_in]]) { - const float2 a_particlePos = tint_symbol.a_particlePos; - const float2 a_particleVel = tint_symbol.a_particleVel; - const float2 a_pos = tint_symbol.a_pos; + float2 const a_particlePos = tint_symbol.a_particlePos; + float2 const a_particleVel = tint_symbol.a_particleVel; + float2 const a_pos = tint_symbol.a_pos; float angle = -( atan2(a_particleVel.x, a_particleVel.y)); float2 pos = float2(((a_pos.x * cos(angle)) - (a_pos.y * sin(angle))), ((a_pos.x * sin(angle)) + (a_pos.y * cos(angle)))); return {float4((pos + a_particlePos), 0.0f, 1.0f)}; @@ -46,7 +46,7 @@ fragment tint_symbol_3 frag_main() { } kernel void comp_main(tint_symbol_5 tint_symbol_4 [[stage_in]], constant SimParams& params [[buffer(0)]], device Particles& particlesA [[buffer(1)]], device Particles& particlesB [[buffer(2)]]) { - const uint3 gl_GlobalInvocationID = tint_symbol_4.gl_GlobalInvocationID; + uint3 const gl_GlobalInvocationID = tint_symbol_4.gl_GlobalInvocationID; uint index = gl_GlobalInvocationID.x; if ((index >= 5u)) { return; diff --git a/test/samples/cube.wgsl.expected.msl b/test/samples/cube.wgsl.expected.msl index 4d86279f0e..80dc476ccd 100644 --- a/test/samples/cube.wgsl.expected.msl +++ b/test/samples/cube.wgsl.expected.msl @@ -28,7 +28,7 @@ struct tint_symbol_5 { }; vertex tint_symbol_2 vtx_main(tint_symbol_1 tint_symbol [[stage_in]], constant Uniforms& uniforms [[buffer(0)]]) { - const VertexInput input = {tint_symbol.cur_position, tint_symbol.color}; + VertexInput const input = {tint_symbol.cur_position, tint_symbol.color}; VertexOutput output = {}; output.Position = (uniforms.modelViewProjectionMatrix * input.cur_position); output.vtxFragColor = input.color; @@ -36,7 +36,7 @@ vertex tint_symbol_2 vtx_main(tint_symbol_1 tint_symbol [[stage_in]], constant U } fragment tint_symbol_5 frag_main(tint_symbol_4 tint_symbol_3 [[stage_in]]) { - const float4 fragColor = tint_symbol_3.fragColor; + float4 const fragColor = tint_symbol_3.fragColor; return {fragColor}; } diff --git a/test/samples/triangle.wgsl.expected.msl b/test/samples/triangle.wgsl.expected.msl index 00638c34ff..7c4039b319 100644 --- a/test/samples/triangle.wgsl.expected.msl +++ b/test/samples/triangle.wgsl.expected.msl @@ -13,7 +13,7 @@ struct tint_symbol_3 { constant float2 pos[3] = {float2(0.0f, 0.5f), float2(-0.5f, -0.5f), float2(0.5f, -0.5f)}; vertex tint_symbol_2 vtx_main(tint_symbol_1 tint_symbol [[stage_in]]) { - const int VertexIndex = tint_symbol.VertexIndex; + int const VertexIndex = tint_symbol.VertexIndex; return {float4(pos[VertexIndex], 0.0f, 1.0f)}; }