TEST(TypeManager, GetTypeInstructionWithDecorations) { const std::string text = R"( ; CHECK: OpDecorate [[struct:%\w+]] CPacked ; CHECK: OpMemberDecorate [[struct]] 1 Offset 4 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 ; CHECK: [[struct]] = OpTypeStruct [[uint]] [[uint]] OpCapability Shader OpCapability Kernel OpCapability Linkage OpMemoryModel Logical GLSL450 %uint = OpTypeInt 32 0 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); Integer u32(32, false); Struct st({&u32, &u32}); st.AddDecoration({10}); st.AddMemberDecoration(1, {{35, 4}}); (void)context->get_def_use_mgr(); context->get_type_mgr()->GetTypeInstruction(&st); Match(text, context.get()); }
std::unique_ptr<ir::IRContext> BuildModule(spv_target_env env, MessageConsumer consumer, const std::string& text, uint32_t assemble_options) { SpirvTools t(env); t.SetMessageConsumer(consumer); std::vector<uint32_t> binary; if (!t.Assemble(text, &binary, assemble_options)) return nullptr; return BuildModule(env, consumer, binary.data(), binary.size()); }
std::vector<uint32_t> ReductionPass::TryApplyReduction( const std::vector<uint32_t>& binary) { // We represent modules as binaries because (a) attempts at reduction need to // end up in binary form to be passed on to SPIR-V-consuming tools, and (b) // when we apply a reduction step we need to do it on a fresh version of the // module as if the reduction step proves to be uninteresting we need to // backtrack; re-parsing from binary provides a very clean way of cloning the // module. std::unique_ptr<opt::IRContext> context = BuildModule(target_env_, consumer_, binary.data(), binary.size()); assert(context); std::vector<std::unique_ptr<ReductionOpportunity>> opportunities = finder_->GetAvailableOpportunities(context.get()); if (!is_initialized_) { is_initialized_ = true; index_ = 0; granularity_ = (uint32_t)opportunities.size(); } if (opportunities.empty()) { granularity_ = 1; return std::vector<uint32_t>(); } assert(granularity_ > 0); if (index_ >= opportunities.size()) { index_ = 0; granularity_ = std::max((uint32_t)1, granularity_ / 2); return std::vector<uint32_t>(); } for (uint32_t i = index_; i < std::min(index_ + granularity_, (uint32_t)opportunities.size()); ++i) { opportunities[i]->TryToApply(); } index_ += granularity_; std::vector<uint32_t> result; context->module()->ToBinary(&result, false); return result; }
TEST(TypeManager, GetPointerToAmbiguousType2) { const std::string text = R"( ; CHECK: [[struct1:%\w+]] = OpTypeStruct ; CHECK: [[struct2:%\w+]] = OpTypeStruct ; CHECK: OpTypePointer Function [[struct1]] ; CHECK: OpTypePointer Function [[struct2]] OpCapability Shader OpCapability Kernel OpCapability Linkage OpMemoryModel Logical GLSL450 %uint = OpTypeInt 32 0 %1 = OpTypeStruct %uint %2 = OpTypeStruct %uint %3 = OpTypePointer Function %1 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); context->get_type_mgr()->FindPointerToType(2, SpvStorageClassFunction); Match(text, context.get()); }
TEST(TypeManager, LookupType) { const std::string text = R"( %void = OpTypeVoid %uint = OpTypeInt 32 0 %int = OpTypeInt 32 1 %vec2 = OpTypeVector %int 2 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); EXPECT_NE(context, nullptr); TypeManager manager(nullptr, context.get()); Void voidTy; EXPECT_EQ(manager.GetId(&voidTy), 1u); Integer uintTy(32, false); EXPECT_EQ(manager.GetId(&uintTy), 2u); Integer intTy(32, true); EXPECT_EQ(manager.GetId(&intTy), 3u); Integer intTy2(32, true); Vector vecTy(&intTy2, 2u); EXPECT_EQ(manager.GetId(&vecTy), 4u); } TEST(TypeManager, RemoveId) { const std::string text = R"( OpCapability Shader OpCapability Linkage OpMemoryModel Logical GLSL450 %1 = OpTypeInt 32 0 %2 = OpTypeInt 32 1 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); context->get_type_mgr()->RemoveId(1u); ASSERT_EQ(context->get_type_mgr()->GetType(1u), nullptr); ASSERT_NE(context->get_type_mgr()->GetType(2u), nullptr); context->get_type_mgr()->RemoveId(2u); ASSERT_EQ(context->get_type_mgr()->GetType(1u), nullptr); ASSERT_EQ(context->get_type_mgr()->GetType(2u), nullptr); } TEST(TypeManager, RemoveIdNonDuplicateAmbiguousType) { const std::string text = R"( OpCapability Shader OpCapability Linkage OpMemoryModel Logical GLSL450 %1 = OpTypeInt 32 0 %2 = OpTypeStruct %1 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); Integer u32(32, false); Struct st({&u32}); ASSERT_EQ(context->get_type_mgr()->GetId(&st), 2u); context->get_type_mgr()->RemoveId(2u); ASSERT_EQ(context->get_type_mgr()->GetType(2u), nullptr); ASSERT_EQ(context->get_type_mgr()->GetId(&st), 0u); } TEST(TypeManager, RemoveIdDuplicateAmbiguousType) { const std::string text = R"( OpCapability Shader OpCapability Linkage OpMemoryModel Logical GLSL450 %1 = OpTypeInt 32 0 %2 = OpTypeStruct %1 %3 = OpTypeStruct %1 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); Integer u32(32, false); Struct st({&u32}); uint32_t id = context->get_type_mgr()->GetId(&st); ASSERT_NE(id, 0u); uint32_t toRemove = id == 2u ? 2u : 3u; uint32_t toStay = id == 2u ? 3u : 2u; context->get_type_mgr()->RemoveId(toRemove); ASSERT_EQ(context->get_type_mgr()->GetType(toRemove), nullptr); ASSERT_EQ(context->get_type_mgr()->GetId(&st), toStay); } TEST(TypeManager, RemoveIdDoesntUnmapOtherTypes) { const std::string text = R"( OpCapability Shader OpMemoryModel Logical GLSL450 %1 = OpTypeInt 32 0 %2 = OpTypeStruct %1 %3 = OpTypeStruct %1 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); Integer u32(32, false); Struct st({&u32}); EXPECT_EQ(1u, context->get_type_mgr()->GetId(&u32)); uint32_t id = context->get_type_mgr()->GetId(&st); ASSERT_NE(id, 0u); uint32_t toRemove = id == 2u ? 3u : 2u; uint32_t toStay = id == 2u ? 2u : 3u; context->get_type_mgr()->RemoveId(toRemove); ASSERT_EQ(context->get_type_mgr()->GetType(toRemove), nullptr); ASSERT_EQ(context->get_type_mgr()->GetId(&st), toStay); } TEST(TypeManager, GetTypeAndPointerType) { const std::string text = R"( OpCapability Shader OpCapability Linkage OpMemoryModel Logical GLSL450 %1 = OpTypeInt 32 0 %2 = OpTypeStruct %1 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); Integer u32(32, false); Pointer u32Ptr(&u32, SpvStorageClassFunction); Struct st({&u32}); Pointer stPtr(&st, SpvStorageClassInput); auto pair = context->get_type_mgr()->GetTypeAndPointerType( 3u, SpvStorageClassFunction); ASSERT_EQ(nullptr, pair.first); ASSERT_EQ(nullptr, pair.second); pair = context->get_type_mgr()->GetTypeAndPointerType( 1u, SpvStorageClassFunction); ASSERT_TRUE(pair.first->IsSame(&u32)); ASSERT_TRUE(pair.second->IsSame(&u32Ptr)); pair = context->get_type_mgr()->GetTypeAndPointerType(2u, SpvStorageClassInput); ASSERT_TRUE(pair.first->IsSame(&st)); ASSERT_TRUE(pair.second->IsSame(&stPtr)); } TEST(TypeManager, DuplicateType) { const std::string text = R"( OpCapability Shader OpMemoryModel Logical GLSL450 %1 = OpTypeInt 32 0 %2 = OpTypeInt 32 0 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); const Type* type1 = context->get_type_mgr()->GetType(1u); const Type* type2 = context->get_type_mgr()->GetType(2u); EXPECT_NE(type1, nullptr); EXPECT_NE(type2, nullptr); EXPECT_EQ(*type1, *type2); } TEST(TypeManager, MultipleStructs) { const std::string text = R"( OpCapability Shader OpMemoryModel Logical GLSL450 OpDecorate %3 Constant %1 = OpTypeInt 32 0 %2 = OpTypeStruct %1 %3 = OpTypeStruct %1 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); const Type* type1 = context->get_type_mgr()->GetType(2u); const Type* type2 = context->get_type_mgr()->GetType(3u); EXPECT_NE(type1, nullptr); EXPECT_NE(type2, nullptr); EXPECT_FALSE(type1->IsSame(type2)); } TEST(TypeManager, RemovingIdAvoidsUseAfterFree) { const std::string text = R"( OpCapability Shader OpMemoryModel Logical GLSL450 %1 = OpTypeInt 32 0 %2 = OpTypeStruct %1 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); Integer u32(32, false); Struct st({&u32}); const Type* type = context->get_type_mgr()->GetType(2u); EXPECT_NE(type, nullptr); context->get_type_mgr()->RemoveId(1u); EXPECT_TRUE(type->IsSame(&st)); } TEST(TypeManager, RegisterAndRemoveId) { const std::string text = R"( OpCapability Shader OpMemoryModel Logical GLSL450 %1 = OpTypeInt 32 0 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); uint32_t id = 2u; { // Ensure that u32 goes out of scope. Integer u32(32, false); Struct st({&u32}); context->get_type_mgr()->RegisterType(id, st); } context->get_type_mgr()->RemoveId(id); EXPECT_EQ(nullptr, context->get_type_mgr()->GetType(id)); } TEST(TypeManager, RegisterAndRemoveIdAllTypes) { const std::string text = R"( OpCapability Shader OpMemoryModel Logical GLSL450 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); std::vector<std::unique_ptr<Type>> types = GenerateAllTypes(); uint32_t id = 1u; for (auto& t : types) { context->get_type_mgr()->RegisterType(id, *t); EXPECT_EQ(*t, *context->get_type_mgr()->GetType(id)); } types.clear(); for (; id > 0; --id) { context->get_type_mgr()->RemoveId(id); EXPECT_EQ(nullptr, context->get_type_mgr()->GetType(id)); } } TEST(TypeManager, RegisterAndRemoveIdWithDecorations) { const std::string text = R"( OpCapability Shader OpMemoryModel Logical GLSL450 %1 = OpTypeInt 32 0 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); uint32_t id = 2u; { Integer u32(32, false); Struct st({&u32, &u32}); st.AddDecoration({10}); st.AddDecoration({11}); st.AddMemberDecoration(0, {{35, 4}}); st.AddMemberDecoration(1, {{35, 4}}); st.AddMemberDecoration(1, {{36, 5}}); context->get_type_mgr()->RegisterType(id, st); EXPECT_EQ(st, *context->get_type_mgr()->GetType(id)); } context->get_type_mgr()->RemoveId(id); EXPECT_EQ(nullptr, context->get_type_mgr()->GetType(id)); } #ifdef SPIRV_EFFCEE TEST(TypeManager, GetTypeInstructionInt) { const std::string text = R"( ; CHECK: OpTypeInt 32 0 ; CHECK: OpTypeInt 16 1 OpCapability Shader OpCapability Int16 OpCapability Linkage OpMemoryModel Logical GLSL450 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); EXPECT_NE(context, nullptr); Integer uint_32(32, false); context->get_type_mgr()->GetTypeInstruction(&uint_32); Integer int_16(16, true); context->get_type_mgr()->GetTypeInstruction(&int_16); Match(text, context.get()); } TEST(TypeManager, GetTypeInstructionDuplicateInts) { const std::string text = R"( ; CHECK: OpTypeInt 32 0 ; CHECK-NOT: OpType OpCapability Shader OpCapability Linkage OpMemoryModel Logical GLSL450 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); EXPECT_NE(context, nullptr); Integer uint_32(32, false); uint32_t id = context->get_type_mgr()->GetTypeInstruction(&uint_32); Integer other(32, false); EXPECT_EQ(context->get_type_mgr()->GetTypeInstruction(&other), id); Match(text, context.get()); } TEST(TypeManager, GetTypeInstructionAllTypes) { const std::string text = R"( ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 ; CHECK: [[input_ptr:%\w+]] = OpTypePointer Input [[uint]] ; CHECK: [[uniform_ptr:%\w+]] = OpTypePointer Uniform [[uint]] ; CHECK: [[uint24:%\w+]] = OpConstant [[uint]] 24 ; CHECK: [[uint42:%\w+]] = OpConstant [[uint]] 42 ; CHECK: [[uint100:%\w+]] = OpConstant [[uint]] 100 ; CHECK: [[void:%\w+]] = OpTypeVoid ; CHECK: [[bool:%\w+]] = OpTypeBool ; CHECK: [[s32:%\w+]] = OpTypeInt 32 1 ; CHECK: OpTypeInt 64 1 ; CHECK: [[u64:%\w+]] = OpTypeInt 64 0 ; CHECK: [[f32:%\w+]] = OpTypeFloat 32 ; CHECK: OpTypeFloat 64 ; CHECK: OpTypeVector [[s32]] 2 ; CHECK: [[v3s32:%\w+]] = OpTypeVector [[s32]] 3 ; CHECK: OpTypeVector [[u64]] 4 ; CHECK: [[v3f32:%\w+]] = OpTypeVector [[f32]] 3 ; CHECK: OpTypeMatrix [[v3s32]] 3 ; CHECK: OpTypeMatrix [[v3s32]] 4 ; CHECK: OpTypeMatrix [[v3f32]] 4 ; CHECK: [[image1:%\w+]] = OpTypeImage [[s32]] 2D 0 0 0 0 Rg8 ReadOnly ; CHECK: OpTypeImage [[s32]] 2D 0 1 0 0 Rg8 ReadOnly ; CHECK: OpTypeImage [[s32]] 3D 0 1 0 0 Rg8 ReadOnly ; CHECK: [[image2:%\w+]] = OpTypeImage [[void]] 3D 0 1 0 1 Rg8 ReadWrite ; CHECK: OpTypeSampler ; CHECK: OpTypeSampledImage [[image1]] ; CHECK: OpTypeSampledImage [[image2]] ; CHECK: OpTypeArray [[f32]] [[uint100]] ; CHECK: [[a42f32:%\w+]] = OpTypeArray [[f32]] [[uint42]] ; CHECK: OpTypeArray [[u64]] [[uint24]] ; CHECK: OpTypeRuntimeArray [[v3f32]] ; CHECK: [[rav3s32:%\w+]] = OpTypeRuntimeArray [[v3s32]] ; CHECK: OpTypeStruct [[s32]] ; CHECK: [[sts32f32:%\w+]] = OpTypeStruct [[s32]] [[f32]] ; CHECK: OpTypeStruct [[u64]] [[a42f32]] [[rav3s32]] ; CHECK: OpTypeOpaque "" ; CHECK: OpTypeOpaque "hello" ; CHECK: OpTypeOpaque "world" ; CHECK: OpTypePointer Input [[f32]] ; CHECK: OpTypePointer Function [[sts32f32]] ; CHECK: OpTypePointer Function [[a42f32]] ; CHECK: OpTypeFunction [[void]] ; CHECK: OpTypeFunction [[void]] [[bool]] ; CHECK: OpTypeFunction [[void]] [[bool]] [[s32]] ; CHECK: OpTypeFunction [[s32]] [[bool]] [[s32]] ; CHECK: OpTypeEvent ; CHECK: OpTypeDeviceEvent ; CHECK: OpTypeReserveId ; CHECK: OpTypeQueue ; CHECK: OpTypePipe ReadWrite ; CHECK: OpTypePipe ReadOnly ; CHECK: OpTypeForwardPointer [[input_ptr]] Input ; CHECK: OpTypeForwardPointer [[uniform_ptr]] Input ; CHECK: OpTypeForwardPointer [[uniform_ptr]] Uniform ; CHECK: OpTypePipeStorage ; CHECK: OpTypeNamedBarrier OpCapability Shader OpCapability Int64 OpCapability Linkage OpMemoryModel Logical GLSL450 %uint = OpTypeInt 32 0 %1 = OpTypePointer Input %uint %2 = OpTypePointer Uniform %uint %24 = OpConstant %uint 24 %42 = OpConstant %uint 42 %100 = OpConstant %uint 100 )"; std::unique_ptr<IRContext> context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); EXPECT_NE(context, nullptr); std::vector<std::unique_ptr<Type>> types = GenerateAllTypes(); for (auto& t : types) { context->get_type_mgr()->GetTypeInstruction(t.get()); } Match(text, context.get(), false); }