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); }
void CLProgramGenerator::goGenerator() { // Initialise probabilies. CLExpression::InitProbabilityTable(); CLStatement::InitProbabilityTable(); // Create vector types. Vector::GenerateVectorTypes(); // Initialise function tables. FunctionInvocationBuiltIn::InitTables(); // Initialise Variable objects used for thread identifiers. ExpressionID::Initialise(); // Initialize runtime parameters; InitRuntimeParameters(); // Initalize atomic parameters if (CLOptions::atomics()) ExpressionAtomic::InitAtomics(); // Initialise buffers used for inter-thread communication. StatementComm::InitBuffers(); // Initialise Message Passing data. MessagePassing::Initialise(); // Expects argc, argv and seed. These vars should really be in the output_mgr. output_mgr_->OutputHeader(0, NULL, seed_); // This creates the random program, the rest handles post-processing and // outputting the program. GenerateAllTypes(); GenerateFunctions(); // If tracking divergence is set, perform the tracking now. std::unique_ptr<Divergence> div; if (CLOptions::track_divergence()) { div.reset(new Divergence()); div->ProcessEntryFunction(GetFirstFunction()); } // If EMI block generation is set, prune them. if (CLOptions::emi()) EMIController::GetEMIController()->PruneEMISections(); // If atomic blocks are generated, add operations for the special values if (CLOptions::atomics()) StatementAtomicResult::GenSpecialVals(); // If atomic reductions are generated, add the hash buffer if (CLOptions::atomic_reductions()) StatementAtomicReduction::RecordBuffer(); // If Message Passing is enabled, create orderings and message updates. if (CLOptions::message_passing()) MessagePassing::CreateMessageOrderings(); // At this point, all the global variables that have been created throughout // program generation should have been created. Any global variables added to // VariableSelector's global list after this point must be added to globals // manually, or the name will not be prepended with the global struct. Globals *globals = Globals::GetGlobals(); // Once the global struct is created, we add the global memory buffers. // Adding global memory buffers to do with atomic expressions. if (CLOptions::atomics()) { ExpressionAtomic::AddVarsToGlobals(globals); } // Add the reduction variables for atomic reductions to the global struct if (CLOptions::atomic_reductions()) StatementAtomicReduction::AddVarsToGlobals(globals); // Now add the input data for EMI sections if specified. if (CLOptions::emi()) for (MemoryBuffer *mb : *EMIController::GetEMIController()->GetItemisedEMIInput()) globals->AddGlobalMemoryBuffer(mb); // Add the 9 variables used for the identifiers. if (CLOptions::fake_divergence()) ExpressionID::AddVarsToGlobals(globals); // Add buffers used for inter-thread comm. if (CLOptions::inter_thread_comm()) StatementComm::AddVarsToGlobals(globals); // Add messages for message passing. if (CLOptions::message_passing()) MessagePassing::AddMessageVarsToGlobals(globals); // If barriers have been set, use the divergence information to place them. if (CLOptions::barriers()) { if (CLOptions::divergence()) GenerateBarriers(div.get(), globals); else { /*TODO Non-div barriers*/ } } if (CLOptions::small()) CLSmith::CLVariable::ParseUnusedVars(); // Output the whole program. output_mgr_->Output(); // Release any singleton instances used. Globals::ReleaseGlobals(); EMIController::ReleaseEMIController(); }