Validation of OpEntryPoint usage.
authorEhsan Nasiri <ehsann@google.com>
Mon, 9 Jan 2017 16:10:52 +0000 (11:10 -0500)
committerDavid Neto <dneto@google.com>
Fri, 13 Jan 2017 21:15:11 +0000 (16:15 -0500)
According to the SPIRV Spec (2.16.1):
* There is at least one OpEntryPoint instruction, unless the Linkage
capability is being used.

* No function can be targeted by both an OpEntryPoint instruction and an
OpFunctionCall instruction.

Also updated unit tests to includ OpEntryPoint.

12 files changed:
source/val/validation_state.h
source/validate.cpp
test/c_interface_test.cpp
test/cpp_interface_test.cpp
test/val/val_capability_test.cpp
test/val/val_cfg_test.cpp
test/val/val_data_test.cpp
test/val/val_id_test.cpp
test/val/val_layout_test.cpp
test/val/val_limits_test.cpp
test/val/val_ssa_test.cpp
test/val/val_storage_test.cpp

index 5abf9c3..a4a4140 100644 (file)
@@ -129,6 +129,16 @@ class ValidationState_t {
   std::vector<uint32_t>& entry_points() { return entry_points_; }
   const std::vector<uint32_t>& entry_points() const { return entry_points_; }
 
+  /// Inserts an <id> to the set of functions that are target of OpFunctionCall.
+  void AddFunctionCallTarget(const uint32_t id) {
+    function_call_targets_.insert(id);
+  }
+
+  /// Returns whether or not a function<id> is the target of OpFunctionCall.
+  bool IsFunctionCallTarget(const uint32_t id) {
+    return (function_call_targets_.find(id) != function_call_targets_.end());
+  }
+
   /// Registers the capability and its dependent capabilities
   void RegisterCapability(SpvCapability cap);
 
@@ -255,6 +265,9 @@ class ValidationState_t {
   /// IDs that are entry points, ie, arguments to OpEntryPoint.
   std::vector<uint32_t> entry_points_;
 
+  /// Functions IDs that are target of OpFunctionCall.
+  std::unordered_set<uint32_t> function_call_targets_;
+
   /// ID Bound from the Header
   uint32_t id_bound_;
 
index fe6c4c4..c3a7c9e 100644 (file)
@@ -120,8 +120,12 @@ spv_result_t ProcessInstruction(void* user_data,
                                 const spv_parsed_instruction_t* inst) {
   ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
   _.increment_instruction_count();
-  if (static_cast<SpvOp>(inst->opcode) == SpvOpEntryPoint)
+  if (static_cast<SpvOp>(inst->opcode) == SpvOpEntryPoint) {
     _.entry_points().push_back(inst->words[2]);
+  }
+  if (static_cast<SpvOp>(inst->opcode) == SpvOpFunctionCall) {
+    _.AddFunctionCallTarget(inst->words[3]);
+  }
 
   DebugInstructionPass(_, inst);
   if (auto error = DataRulesPass(_, inst)) return error;
@@ -235,6 +239,27 @@ spv_result_t ValidateBinaryUsingContextAndValidationState(
   if (auto error = UpdateIdUse(*vstate)) return error;
   if (auto error = CheckIdDefinitionDominateUse(*vstate)) return error;
 
+  // Entry point validation. Based on 2.16.1 (Universal Validation Rules) of the
+  // SPIRV spec:
+  // * There is at least one OpEntryPoint instruction, unless the Linkage
+  // capability is being used.
+  // * No function can be targeted by both an OpEntryPoint instruction and an
+  // OpFunctionCall instruction.
+  if (vstate->entry_points().empty() &&
+      !vstate->HasCapability(SpvCapabilityLinkage)) {
+    return vstate->diag(SPV_ERROR_INVALID_BINARY)
+           << "No OpEntryPoint instruction was found. This is only allowed if "
+              "the Linkage capability is being used.";
+  }
+  for (const auto& entry_point : vstate->entry_points()) {
+    if (vstate->IsFunctionCallTarget(entry_point)) {
+      return vstate->diag(SPV_ERROR_INVALID_BINARY)
+             << "A function (" << entry_point
+             << ") may not be targeted by both an OpEntryPoint instruction and "
+                "an OpFunctionCall instruction.";
+    }
+  }
+
   // NOTE: Copy each instruction for easier processing
   std::vector<spv_instruction_t> instructions;
   uint64_t index = SPV_INDEX_INSTRUCTION;
index 6defbec..168ff13 100644 (file)
@@ -26,7 +26,9 @@ using namespace spvtools;
 TEST(CInterface, DefaultConsumerNullDiagnosticForValidInput) {
   auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
   const char input_text[] =
-      "OpCapability Shader\nOpMemoryModel Logical GLSL450";
+      "OpCapability Shader\n"
+      "OpCapability Linkage\n"
+      "OpMemoryModel Logical GLSL450";
 
   spv_binary binary = nullptr;
   EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text,
index e492a63..307ee93 100644 (file)
@@ -173,8 +173,10 @@ TEST(CppInterface, DisassembleWithWrongTargetEnv) {
 }
 
 TEST(CppInterface, SuccessfulValidation) {
-  const std::string input_text =
-      "OpCapability Shader\nOpMemoryModel Logical GLSL450";
+  const std::string input_text = R"(
+    OpCapability Shader
+    OpCapability Linkage
+    OpMemoryModel Logical GLSL450)";
   SpirvTools t(SPV_ENV_UNIVERSAL_1_1);
   int invocation_count = 0;
   t.SetMessageConsumer([&invocation_count](spv_message_level_t, const char*,
@@ -189,8 +191,10 @@ TEST(CppInterface, SuccessfulValidation) {
 }
 
 TEST(CppInterface, ValidateOverloads) {
-  const std::string input_text =
-      "OpCapability Shader\nOpMemoryModel Logical GLSL450";
+  const std::string input_text = R"(
+    OpCapability Shader
+    OpCapability Linkage
+    OpMemoryModel Logical GLSL450)";
   SpirvTools t(SPV_ENV_UNIVERSAL_1_1);
   std::vector<uint32_t> binary;
   EXPECT_TRUE(t.Assemble(input_text, &binary));
index 2604187..65345d6 100644 (file)
@@ -112,6 +112,7 @@ using ValidateCapabilityOpenGL40 = spvtest::ValidateBase<CapTestParameter>;
 TEST_F(ValidateCapability, Default) {
   const char str[] = R"(
             OpCapability Kernel
+            OpCapability Linkage
             OpCapability Matrix
             OpMemoryModel Logical OpenCL
 %f32      = OpTypeFloat 32
@@ -449,23 +450,41 @@ INSTANTIATE_TEST_CASE_P(AddressingAndMemoryModel, ValidateCapability,
                             ValuesIn(AllCapabilities()),
                             Values(
 make_pair(" OpCapability Shader"
-          " OpMemoryModel Logical Simple",     AllCapabilities()),
+          " OpMemoryModel Logical Simple"
+          " OpEntryPoint Vertex %func \"shader\"" +
+          string(kVoidFVoid),     AllCapabilities()),
 make_pair(" OpCapability Shader"
-          " OpMemoryModel Logical GLSL450",    AllCapabilities()),
+          " OpMemoryModel Logical GLSL450"
+          " OpEntryPoint Vertex %func \"shader\"" +
+          string(kVoidFVoid),    AllCapabilities()),
 make_pair(" OpCapability Kernel"
-          " OpMemoryModel Logical OpenCL",     AllCapabilities()),
+          " OpMemoryModel Logical OpenCL"
+          " OpEntryPoint Kernel %func \"compute\"" +
+          string(kVoidFVoid),     AllCapabilities()),
 make_pair(" OpCapability Shader"
-          " OpMemoryModel Physical32 Simple",  AddressesDependencies()),
+          " OpMemoryModel Physical32 Simple"
+          " OpEntryPoint Vertex %func \"shader\"" +
+          string(kVoidFVoid),  AddressesDependencies()),
 make_pair(" OpCapability Shader"
-          " OpMemoryModel Physical32 GLSL450", AddressesDependencies()),
+          " OpMemoryModel Physical32 GLSL450"
+          " OpEntryPoint Vertex %func \"shader\"" +
+          string(kVoidFVoid), AddressesDependencies()),
 make_pair(" OpCapability Kernel"
-          " OpMemoryModel Physical32 OpenCL",  AddressesDependencies()),
+          " OpMemoryModel Physical32 OpenCL"
+          " OpEntryPoint Kernel %func \"compute\"" +
+          string(kVoidFVoid),  AddressesDependencies()),
 make_pair(" OpCapability Shader"
-          " OpMemoryModel Physical64 Simple",  AddressesDependencies()),
+          " OpMemoryModel Physical64 Simple"
+          " OpEntryPoint Vertex %func \"shader\"" +
+          string(kVoidFVoid),  AddressesDependencies()),
 make_pair(" OpCapability Shader"
-          " OpMemoryModel Physical64 GLSL450", AddressesDependencies()),
+          " OpMemoryModel Physical64 GLSL450"
+          " OpEntryPoint Vertex %func \"shader\"" +
+          string(kVoidFVoid), AddressesDependencies()),
 make_pair(" OpCapability Kernel"
-          " OpMemoryModel Physical64 OpenCL",  AddressesDependencies())
+          " OpMemoryModel Physical64 OpenCL"
+          " OpEntryPoint Kernel %func \"compute\"" +
+          string(kVoidFVoid),  AddressesDependencies())
 )),);
 
 INSTANTIATE_TEST_CASE_P(ExecutionMode, ValidateCapability,
@@ -628,45 +647,65 @@ INSTANTIATE_TEST_CASE_P(StorageClass, ValidateCapability,
                             ValuesIn(AllCapabilities()),
                             Values(
 make_pair(string(kGLSL450MemoryModel) +
+          " OpEntryPoint Vertex %func \"shader\"" +
           " %intt = OpTypeInt 32 0\n"
           " %ptrt = OpTypePointer UniformConstant %intt\n"
-          " %var = OpVariable %ptrt UniformConstant\n", AllCapabilities()),
+          " %var = OpVariable %ptrt UniformConstant\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          " OpEntryPoint Kernel %func \"compute\"" +
           " %intt = OpTypeInt 32 0\n"
           " %ptrt = OpTypePointer Input %intt"
-          " %var = OpVariable %ptrt Input\n", AllCapabilities()),
+          " %var = OpVariable %ptrt Input\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          " OpEntryPoint Vertex %func \"shader\"" +
           " %intt = OpTypeInt 32 0\n"
           " %ptrt = OpTypePointer Uniform %intt\n"
-          " %var = OpVariable %ptrt Uniform\n", ShaderDependencies()),
+          " %var = OpVariable %ptrt Uniform\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          " OpEntryPoint Vertex %func \"shader\"" +
           " %intt = OpTypeInt 32 0\n"
           " %ptrt = OpTypePointer Output %intt\n"
-          " %var = OpVariable %ptrt Output\n", ShaderDependencies()),
+          " %var = OpVariable %ptrt Output\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          " OpEntryPoint Vertex %func \"shader\"" +
           " %intt = OpTypeInt 32 0\n"
           " %ptrt = OpTypePointer Workgroup %intt\n"
-          " %var = OpVariable %ptrt Workgroup\n", AllCapabilities()),
+          " %var = OpVariable %ptrt Workgroup\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kGLSL450MemoryModel) +
+          " OpEntryPoint Vertex %func \"shader\"" +
           " %intt = OpTypeInt 32 0\n"
           " %ptrt = OpTypePointer CrossWorkgroup %intt\n"
-          " %var = OpVariable %ptrt CrossWorkgroup\n", AllCapabilities()),
+          " %var = OpVariable %ptrt CrossWorkgroup\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          " OpEntryPoint Kernel %func \"compute\"" +
           " %intt = OpTypeInt 32 0\n"
           " %ptrt = OpTypePointer Private %intt\n"
-          " %var = OpVariable %ptrt Private\n", ShaderDependencies()),
+          " %var = OpVariable %ptrt Private\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          " OpEntryPoint Kernel %func \"compute\"" +
           " %intt = OpTypeInt 32 0\n"
           " %ptrt = OpTypePointer PushConstant %intt\n"
-          " %var = OpVariable %ptrt PushConstant\n", ShaderDependencies()),
+          " %var = OpVariable %ptrt PushConstant\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          " OpEntryPoint Vertex %func \"shader\"" +
           " %intt = OpTypeInt 32 0\n"
           " %ptrt = OpTypePointer AtomicCounter %intt\n"
-          " %var = OpVariable %ptrt AtomicCounter\n", vector<string>{"AtomicStorage"}),
+          " %var = OpVariable %ptrt AtomicCounter\n" + string(kVoidFVoid),
+          vector<string>{"AtomicStorage"}),
 make_pair(string(kGLSL450MemoryModel) +
+          " OpEntryPoint Vertex %func \"shader\"" +
           " %intt = OpTypeInt 32 0\n"
           " %ptrt = OpTypePointer Image %intt\n"
-          " %var = OpVariable %ptrt Image\n", AllCapabilities())
+          " %var = OpVariable %ptrt Image\n" + string(kVoidFVoid),
+          AllCapabilities())
 )),);
 
 INSTANTIATE_TEST_CASE_P(Dim, ValidateCapability,
@@ -675,38 +714,45 @@ INSTANTIATE_TEST_CASE_P(Dim, ValidateCapability,
                             Values(
 make_pair(" OpCapability ImageBasic" +
           string(kOpenCLMemoryModel) +
+          string(" OpEntryPoint Kernel %func \"compute\"") +
           " %voidt = OpTypeVoid"
-          " %imgt = OpTypeImage %voidt 1D 0 0 0 0 Unknown",
+          " %imgt = OpTypeImage %voidt 1D 0 0 0 0 Unknown" + string(kVoidFVoid),
           Sampled1DDependencies()),
 make_pair(" OpCapability ImageBasic" +
           string(kOpenCLMemoryModel) +
+          string(" OpEntryPoint Kernel %func \"compute\"") +
           " %voidt = OpTypeVoid"
-          " %imgt = OpTypeImage %voidt 2D 0 0 0 0 Unknown",
+          " %imgt = OpTypeImage %voidt 2D 0 0 0 0 Unknown" + string(kVoidFVoid),
           AllCapabilities()),
 make_pair(" OpCapability ImageBasic" +
           string(kOpenCLMemoryModel) +
+          string(" OpEntryPoint Kernel %func \"compute\"") +
           " %voidt = OpTypeVoid"
-          " %imgt = OpTypeImage %voidt 3D 0 0 0 0 Unknown",
+          " %imgt = OpTypeImage %voidt 3D 0 0 0 0 Unknown" + string(kVoidFVoid),
           AllCapabilities()),
 make_pair(" OpCapability ImageBasic" +
           string(kOpenCLMemoryModel) +
+          string(" OpEntryPoint Kernel %func \"compute\"") +
           " %voidt = OpTypeVoid"
-          " %imgt = OpTypeImage %voidt Cube 0 0 0 0 Unknown",
+          " %imgt = OpTypeImage %voidt Cube 0 0 0 0 Unknown" + string(kVoidFVoid),
           ShaderDependencies()),
 make_pair(" OpCapability ImageBasic" +
           string(kOpenCLMemoryModel) +
+          string(" OpEntryPoint Kernel %func \"compute\"") +
           " %voidt = OpTypeVoid"
-          " %imgt = OpTypeImage %voidt Rect 0 0 0 0 Unknown",
+          " %imgt = OpTypeImage %voidt Rect 0 0 0 0 Unknown" + string(kVoidFVoid),
           SampledRectDependencies()),
 make_pair(" OpCapability ImageBasic" +
           string(kOpenCLMemoryModel) +
+          string(" OpEntryPoint Kernel %func \"compute\"") +
           " %voidt = OpTypeVoid"
-          " %imgt = OpTypeImage %voidt Buffer 0 0 0 0 Unknown",
+          " %imgt = OpTypeImage %voidt Buffer 0 0 0 0 Unknown" + string(kVoidFVoid),
           SampledBufferDependencies()),
 make_pair(" OpCapability ImageBasic" +
           string(kOpenCLMemoryModel) +
+          string(" OpEntryPoint Kernel %func \"compute\"") +
           " %voidt = OpTypeVoid"
-          " %imgt = OpTypeImage %voidt SubpassData 0 0 0 2 Unknown",
+          " %imgt = OpTypeImage %voidt SubpassData 0 0 0 2 Unknown" + string(kVoidFVoid),
           vector<string>{"InputAttachment"})
 )),);
 
@@ -717,24 +763,34 @@ INSTANTIATE_TEST_CASE_P(SamplerAddressingMode, ValidateCapability,
                             ValuesIn(AllCapabilities()),
                             Values(
 make_pair(string(kGLSL450MemoryModel) +
+          " OpEntryPoint Vertex %func \"shader\""
           " %samplert = OpTypeSampler"
-          " %sampler = OpConstantSampler %samplert None 1 Nearest",
+          " %sampler = OpConstantSampler %samplert None 1 Nearest" +
+          string(kVoidFVoid),
           vector<string>{"LiteralSampler"}),
 make_pair(string(kGLSL450MemoryModel) +
+          " OpEntryPoint Vertex %func \"shader\""
           " %samplert = OpTypeSampler"
-          " %sampler = OpConstantSampler %samplert ClampToEdge 1 Nearest",
+          " %sampler = OpConstantSampler %samplert ClampToEdge 1 Nearest" +
+          string(kVoidFVoid),
           vector<string>{"LiteralSampler"}),
 make_pair(string(kGLSL450MemoryModel) +
+          " OpEntryPoint Vertex %func \"shader\""
           " %samplert = OpTypeSampler"
-          " %sampler = OpConstantSampler %samplert Clamp 1 Nearest",
+          " %sampler = OpConstantSampler %samplert Clamp 1 Nearest" +
+          string(kVoidFVoid),
           vector<string>{"LiteralSampler"}),
 make_pair(string(kGLSL450MemoryModel) +
+          " OpEntryPoint Vertex %func \"shader\""
           " %samplert = OpTypeSampler"
-          " %sampler = OpConstantSampler %samplert Repeat 1 Nearest",
+          " %sampler = OpConstantSampler %samplert Repeat 1 Nearest" +
+          string(kVoidFVoid),
           vector<string>{"LiteralSampler"}),
 make_pair(string(kGLSL450MemoryModel) +
+          " OpEntryPoint Vertex %func \"shader\""
           " %samplert = OpTypeSampler"
-          " %sampler = OpConstantSampler %samplert RepeatMirrored 1 Nearest",
+          " %sampler = OpConstantSampler %samplert RepeatMirrored 1 Nearest" +
+          string(kVoidFVoid),
           vector<string>{"LiteralSampler"})
 )),);
 
@@ -754,128 +810,210 @@ INSTANTIATE_TEST_CASE_P(Decoration, ValidateCapability,
                             ValuesIn(AllCapabilities()),
                             Values(
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt RelaxedPrecision\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Block\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt BufferBlock\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt RowMajor\n"
-          "%intt = OpTypeInt 32 1\n", MatrixDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          MatrixDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt ColMajor\n"
-          "%intt = OpTypeInt 32 1\n", MatrixDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          MatrixDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt ArrayStride 1\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt MatrixStride 1\n"
-          "%intt = OpTypeInt 32 1\n", MatrixDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          MatrixDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt GLSLShared\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt GLSLPacked\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n"
           "OpDecorate %intt CPacked\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt NoPerspective\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Flat\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Patch\n"
-          "%intt = OpTypeInt 32 1\n", TessellationDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          TessellationDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Centroid\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Sample\n"
-          "%intt = OpTypeInt 32 1\n", vector<string>{"SampleRateShading"}),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          vector<string>{"SampleRateShading"}),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Invariant\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Restrict\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Aliased\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Volatile\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n"
           "OpDecorate %intt Constant\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Coherent\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt NonWritable\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt NonReadable\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Uniform\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n"
           "OpDecorate %intt SaturatedConversion\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Stream 0\n"
-          "%intt = OpTypeInt 32 1\n", vector<string>{"GeometryStreams"}),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          vector<string>{"GeometryStreams"}),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Location 0\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Component 0\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Index 0\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Binding 0\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt DescriptorSet 0\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt Offset 0\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt XfbBuffer 0\n"
-          "%intt = OpTypeInt 32 1\n", vector<string>{"TransformFeedback"}),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          vector<string>{"TransformFeedback"}),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt XfbStride 0\n"
-          "%intt = OpTypeInt 32 1\n", vector<string>{"TransformFeedback"}),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          vector<string>{"TransformFeedback"}),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n"
           "OpDecorate %intt FuncParamAttr Zext\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n"
           "OpDecorate %intt FPRoundingMode RTE\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n"
           "OpDecorate %intt FPFastMathMode Fast\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt LinkageAttributes \"other\" Import\n"
-          "%intt = OpTypeInt 32 1\n", vector<string>{"Linkage"}),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          vector<string>{"Linkage"}),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt NoContraction\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n"
           "OpDecorate %intt InputAttachmentIndex 0\n"
-          "%intt = OpTypeInt 32 1\n", vector<string>{"InputAttachment"}),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          vector<string>{"InputAttachment"}),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n"
           "OpDecorate %intt Alignment 4\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies())
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies())
 )),);
 
 // clang-format on
@@ -883,29 +1021,36 @@ INSTANTIATE_TEST_CASE_P(
     DecorationSpecId, ValidateCapability,
     Combine(ValuesIn(AllV10Capabilities()),
             Values(make_pair(string(kOpenCLMemoryModel) +
-                                 "OpDecorate %intt SpecId 1\n"
-                                 "%intt = OpTypeInt 32 1\n",
+                             "OpEntryPoint Vertex %func \"shader\" \n" +
+                             "OpDecorate %intt SpecId 1\n"
+                             "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
                              ShaderDependencies()))), );
 
 INSTANTIATE_TEST_CASE_P(
     DecorationV11, ValidateCapabilityV11,
     Combine(ValuesIn(AllCapabilities()),
             Values(make_pair(string(kOpenCLMemoryModel) +
+                                 "OpEntryPoint Kernel %func \"compute\" \n"
                                  "OpDecorate %p MaxByteOffset 0 "
                                  "%i32 = OpTypeInt 32 1 "
                                  "%pi32 = OpTypePointer Workgroup %i32 "
-                                 "%p = OpVariable %pi32 Workgroup ",
+                                 "%p = OpVariable %pi32 Workgroup " +
+                                 string(kVoidFVoid),
                              AddressesDependencies()),
                    // Trying to test OpDecorate here, but if this fails due to
                    // incorrect OpMemoryModel validation, that must also be
                    // fixed.
                    make_pair(string("OpMemoryModel Logical OpenCL "
+                                    "OpEntryPoint Kernel %func \"compute\" \n"
                                     "OpDecorate %intt SpecId 1 "
-                                    "%intt = OpTypeInt 32 1 "),
+                                    "%intt = OpTypeInt 32 1 ") +
+                                 string(kVoidFVoid),
                              KernelDependencies()),
                    make_pair(string("OpMemoryModel Logical Simple "
+                                    "OpEntryPoint Vertex %func \"shader\" \n"
                                     "OpDecorate %intt SpecId 1 "
-                                    "%intt = OpTypeInt 32 1 "),
+                                    "%intt = OpTypeInt 32 1 ") +
+                                 string(kVoidFVoid),
                              ShaderDependencies()))), );
 // clang-format off
 
@@ -914,137 +1059,223 @@ INSTANTIATE_TEST_CASE_P(BuiltIn, ValidateCapability,
                             ValuesIn(AllCapabilities()),
                             Values(
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn Position\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 // Just mentioning PointSize, ClipDistance, or CullDistance as a BuiltIn does
 // not trigger the requirement for the associated capability.
 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/365
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn PointSize\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn ClipDistance\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn CullDistance\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn VertexId\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn InstanceId\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn PrimitiveId\n"
-          "%intt = OpTypeInt 32 1\n", GeometryTessellationDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          GeometryTessellationDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn InvocationId\n"
-          "%intt = OpTypeInt 32 1\n", GeometryTessellationDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          GeometryTessellationDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn Layer\n"
-          "%intt = OpTypeInt 32 1\n", GeometryDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          GeometryDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn ViewportIndex\n"
-          "%intt = OpTypeInt 32 1\n", vector<string>{"MultiViewport"}),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          vector<string>{"MultiViewport"}),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn TessLevelOuter\n"
-          "%intt = OpTypeInt 32 1\n", TessellationDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          TessellationDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn TessLevelInner\n"
-          "%intt = OpTypeInt 32 1\n", TessellationDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          TessellationDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn TessCoord\n"
-          "%intt = OpTypeInt 32 1\n", TessellationDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          TessellationDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn PatchVertices\n"
-          "%intt = OpTypeInt 32 1\n", TessellationDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          TessellationDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn FragCoord\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn PointCoord\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn FrontFacing\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn SampleId\n"
-          "%intt = OpTypeInt 32 1\n", vector<string>{"SampleRateShading"}),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          vector<string>{"SampleRateShading"}),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn SamplePosition\n"
-          "%intt = OpTypeInt 32 1\n", vector<string>{"SampleRateShading"}),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          vector<string>{"SampleRateShading"}),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn SampleMask\n"
-          "%intt = OpTypeInt 32 1\n", vector<string>{"SampleRateShading"}),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          vector<string>{"SampleRateShading"}),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn FragDepth\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn HelperInvocation\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn VertexIndex\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn InstanceIndex\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn NumWorkgroups\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn WorkgroupSize\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn WorkgroupId\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn LocalInvocationId\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn GlobalInvocationId\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn LocalInvocationIndex\n"
-          "%intt = OpTypeInt 32 1\n", AllCapabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllCapabilities()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn WorkDim\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn GlobalSize\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn EnqueuedWorkgroupSize\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn GlobalOffset\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn GlobalLinearId\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn SubgroupSize\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn SubgroupMaxSize\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn NumSubgroups\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn NumEnqueuedSubgroups\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn SubgroupId\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn SubgroupLocalInvocationId\n"
-          "%intt = OpTypeInt 32 1\n", KernelDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          KernelDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn VertexIndex\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies()),
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "OpDecorate %intt BuiltIn InstanceIndex\n"
-          "%intt = OpTypeInt 32 1\n", ShaderDependencies())
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          ShaderDependencies())
 )),);
 
 // Ensure that mere mention of PointSize, ClipDistance, or CullDistance as
@@ -1057,14 +1288,20 @@ INSTANTIATE_TEST_CASE_P(BuiltIn, ValidateCapabilityVulkan10,
                             ValuesIn(AllV10Capabilities()),
                             Values(
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn PointSize\n"
-          "%intt = OpTypeInt 32 1\n", AllV10Capabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllV10Capabilities()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn ClipDistance\n"
-          "%intt = OpTypeInt 32 1\n", AllV10Capabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllV10Capabilities()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn CullDistance\n"
-          "%intt = OpTypeInt 32 1\n", AllV10Capabilities())
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllV10Capabilities())
 )),);
 
 INSTANTIATE_TEST_CASE_P(BuiltIn, ValidateCapabilityOpenGL40,
@@ -1073,14 +1310,20 @@ INSTANTIATE_TEST_CASE_P(BuiltIn, ValidateCapabilityOpenGL40,
                             ValuesIn(AllV10Capabilities()),
                             Values(
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn PointSize\n"
-          "%intt = OpTypeInt 32 1\n", AllV10Capabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllV10Capabilities()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn ClipDistance\n"
-          "%intt = OpTypeInt 32 1\n", AllV10Capabilities()),
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllV10Capabilities()),
 make_pair(string(kGLSL450MemoryModel) +
+          "OpEntryPoint Vertex %func \"shader\" \n" +
           "OpDecorate %intt BuiltIn CullDistance\n"
-          "%intt = OpTypeInt 32 1\n", AllV10Capabilities())
+          "%intt = OpTypeInt 32 1\n" + string(kVoidFVoid),
+          AllV10Capabilities())
 )),);
 
 // TODO(umar): Selection Control
@@ -1098,9 +1341,11 @@ INSTANTIATE_TEST_CASE_P(MatrixOp, ValidateCapability,
                             ValuesIn(AllCapabilities()),
                             Values(
 make_pair(string(kOpenCLMemoryModel) +
+          "OpEntryPoint Kernel %func \"compute\" \n" +
           "%f32      = OpTypeFloat 32\n"
           "%vec3     = OpTypeVector %f32 3\n"
-          "%mat33    = OpTypeMatrix %vec3 3\n", MatrixDependencies()))),);
+          "%mat33    = OpTypeMatrix %vec3 3\n" + string(kVoidFVoid),
+          MatrixDependencies()))),);
 // clang-format on
 
 // Creates assembly containing an OpImageFetch instruction using operands for
@@ -1112,6 +1357,7 @@ string ImageOperandsTemplate(const string& operands) {
   // clang-format off
   ss << R"(
 OpCapability Kernel
+OpCapability Linkage
 OpMemoryModel Logical OpenCL
 
 %i32 = OpTypeInt 32 1
@@ -1205,6 +1451,7 @@ TEST_F(ValidateCapability, SemanticsIdIsAnIdNotALiteral) {
   // capability.
   const char str[] = R"(
 OpCapability Kernel
+OpCapability Linkage
 OpMemoryModel Logical OpenCL
 
 ;  %i32 has ID 1
index 81c8274..069d019 100644 (file)
@@ -1,4 +1,3 @@
-
 // Copyright (c) 2015-2016 The Khronos Group Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -156,10 +155,12 @@ Block& operator>>(Block& lhs, Block& successor) {
 const char* header(SpvCapability cap) {
   static const char* shader_header =
       "OpCapability Shader\n"
+      "OpCapability Linkage\n"
       "OpMemoryModel Logical GLSL450\n";
 
   static const char* kernel_header =
       "OpCapability Kernel\n"
+      "OpCapability Linkage\n"
       "OpMemoryModel Logical OpenCL\n";
 
   return (cap == SpvCapabilityShader) ? shader_header : kernel_header;
@@ -194,6 +195,7 @@ TEST_P(ValidateCFG, LoopReachableFromEntryButNeverLeadingToReturn) {
   // https://github.com/KhronosGroup/SPIRV-Tools/issues/279
   string str = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
 
            OpName %entry "entry"
@@ -231,6 +233,7 @@ TEST_P(ValidateCFG, LoopUnreachableFromEntryButLeadingToReturn) {
   // post-dominators.
   string str = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
 
            OpName %entry "entry"
@@ -1303,6 +1306,7 @@ TEST_P(ValidateCFG, SingleLatchBlockHeaderContinueTargetIsItselfGood) {
 TEST_F(ValidateCFG, BasicBlockIsEntryBlockOfTwoConstructsGood) {
   std::string spirv = R"(
                OpCapability Shader
+               OpCapability Linkage
                OpMemoryModel Logical GLSL450
        %void = OpTypeVoid
        %bool = OpTypeBool
index 656abce..82d5d00 100644 (file)
@@ -33,6 +33,7 @@ using ValidateData = spvtest::ValidateBase<pair<string, bool>>;
 
 string header = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpMemoryModel Logical GLSL450
 %1 = OpTypeFloat 32
 )";
@@ -40,41 +41,49 @@ string header_with_addresses = R"(
      OpCapability Addresses
      OpCapability Kernel
      OpCapability GenericPointer
+     OpCapability Linkage
      OpMemoryModel Physical32 OpenCL
 )";
 string header_with_vec16_cap = R"(
      OpCapability Shader
      OpCapability Vector16
+     OpCapability Linkage
      OpMemoryModel Logical GLSL450
 %1 = OpTypeFloat 32
 )";
 string header_with_int8 = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpCapability Int8
      OpMemoryModel Logical GLSL450
 )";
 string header_with_int16 = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpCapability Int16
      OpMemoryModel Logical GLSL450
 )";
 string header_with_int64 = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpCapability Int64
      OpMemoryModel Logical GLSL450
 )";
 string header_with_float16 = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpCapability Float16
      OpMemoryModel Logical GLSL450
 )";
 string header_with_float16_buffer = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpCapability Float16Buffer
      OpMemoryModel Logical GLSL450
 )";
 string header_with_float64 = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpCapability Float64
      OpMemoryModel Logical GLSL450
 )";
index fa58ea5..9d58374 100644 (file)
@@ -39,6 +39,7 @@ using ValidateIdWithMessage = spvtest::ValidateBase<bool>;
 
 string kGLSL450MemoryModel = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpCapability Addresses
      OpCapability Pipes
      OpCapability LiteralSampler
index bc49075..e8b4247 100644 (file)
@@ -35,7 +35,7 @@ using std::tuple;
 using std::vector;
 
 using ::testing::StrEq;
-
+using ::testing::HasSubstr;
 using libspirv::spvResultToString;
 
 using pred_type = function<spv_result_t(int)>;
@@ -303,6 +303,7 @@ TEST_F(ValidateLayout, FuncParameterNotImmediatlyAfterFuncBad) {
 TEST_F(ValidateLayout, OpUndefCanAppearInTypeDeclarationSection) {
   string str = R"(
          OpCapability Kernel
+         OpCapability Linkage
          OpMemoryModel Logical OpenCL
 %voidt = OpTypeVoid
 %uintt = OpTypeInt 32 0
@@ -321,6 +322,7 @@ TEST_F(ValidateLayout, OpUndefCanAppearInTypeDeclarationSection) {
 TEST_F(ValidateLayout, OpUndefCanAppearInBlock) {
   string str = R"(
          OpCapability Kernel
+         OpCapability Linkage
          OpMemoryModel Logical OpenCL
 %voidt = OpTypeVoid
 %uintt = OpTypeInt 32 0
@@ -339,6 +341,7 @@ TEST_F(ValidateLayout, OpUndefCanAppearInBlock) {
 TEST_F(ValidateLayout, MissingFunctionEndForFunctionWithBody) {
   const auto s = R"(
 OpCapability Shader
+OpCapability Linkage
 OpMemoryModel Logical GLSL450
 %void = OpTypeVoid
 %tf = OpTypeFunction %void
@@ -356,6 +359,7 @@ OpReturn
 TEST_F(ValidateLayout, MissingFunctionEndForFunctionPrototype) {
   const auto s = R"(
 OpCapability Shader
+OpCapability Linkage
 OpMemoryModel Logical GLSL450
 %void = OpTypeVoid
 %tf = OpTypeFunction %void
@@ -373,6 +377,7 @@ using ValidateOpFunctionParameter = spvtest::ValidateBase<int>;
 TEST_F(ValidateOpFunctionParameter, OpLineBetweenParameters) {
   const auto s = R"(
 OpCapability Shader
+OpCapability Linkage
 OpMemoryModel Logical GLSL450
 %foo_frag = OpString "foo.frag"
 %i32 = OpTypeInt 32 1
@@ -394,6 +399,7 @@ OpFunctionEnd
 TEST_F(ValidateOpFunctionParameter, TooManyParameters) {
   const auto s = R"(
 OpCapability Shader
+OpCapability Linkage
 OpMemoryModel Logical GLSL450
 %i32 = OpTypeInt 32 1
 %tf = OpTypeFunction %i32 %i32 %i32
@@ -413,5 +419,61 @@ OpFunctionEnd
   CompileSuccessfully(s);
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
 }
+
+using ValidateEntryPoint = spvtest::ValidateBase<bool>;
+
+// Tests that not having OpEntryPoint causes an error.
+TEST_F(ValidateEntryPoint, NoEntryPointBad) {
+  std::string spirv = R"(
+      OpCapability Shader
+      OpMemoryModel Logical GLSL450)";
+  CompileSuccessfully(spirv);
+  EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("No OpEntryPoint instruction was found. This is only "
+                        "allowed if the Linkage capability is being used."));
+}
+
+// Invalid. A function may not be a target of both OpEntryPoint and
+// OpFunctionCall.
+TEST_F(ValidateEntryPoint, FunctionIsTargetOfEntryPointAndFunctionCallBad) {
+  std::string spirv = R"(
+           OpCapability Shader
+           OpMemoryModel Logical GLSL450
+           OpEntryPoint Fragment %foo "foo"
+%voidt   = OpTypeVoid
+%funct   = OpTypeFunction %voidt
+%foo     = OpFunction %voidt None %funct
+%entry   = OpLabel
+%recurse = OpFunctionCall %voidt %foo
+           OpReturn
+           OpFunctionEnd
+      )";
+  CompileSuccessfully(spirv);
+  EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("A function (1) may not be targeted by both an OpEntryPoint "
+                "instruction and an OpFunctionCall instruction."));
+}
+
+// Valid. Module with a function but no entry point is valid when Linkage
+// Capability is used.
+TEST_F(ValidateEntryPoint, NoEntryPointWithLinkageCapGood) {
+  std::string spirv = R"(
+           OpCapability Shader
+           OpCapability Linkage
+           OpMemoryModel Logical GLSL450
+%voidt   = OpTypeVoid
+%funct   = OpTypeFunction %voidt
+%foo     = OpFunction %voidt None %funct
+%entry   = OpLabel
+           OpReturn
+           OpFunctionEnd
+  )";
+  CompileSuccessfully(spirv);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
 // TODO(umar): Test optional instructions
 }
index c402e34..5fd336a 100644 (file)
@@ -32,6 +32,7 @@ using ValidateLimits = spvtest::ValidateBase<bool>;
 
 string header = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpMemoryModel Logical GLSL450
 )";
 
@@ -392,9 +393,7 @@ TEST_F(ValidateLimits, ControlFlowDepthBad) {
 // continue target is the loop iteself. It also exercises the case where a loop
 // is unreachable.
 TEST_F(ValidateLimits, ControlFlowNoEntryToLoopGood) {
-  string str = R"(
-           OpCapability Shader
-           OpMemoryModel Logical GLSL450
+  string str = header + R"(
            OpName %entry "entry"
            OpName %loop "loop"
            OpName %exit "exit"
index 09bb9bc..affc5a4 100644 (file)
@@ -35,6 +35,7 @@ using ValidateSSA = spvtest::ValidateBase<pair<string, bool>>;
 TEST_F(ValidateSSA, Default) {
   char str[] = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpMemoryModel Logical GLSL450
      OpEntryPoint GLCompute %3 ""
      OpExecutionMode %3 LocalSize 1 1 1
@@ -52,6 +53,7 @@ TEST_F(ValidateSSA, Default) {
 TEST_F(ValidateSSA, IdUndefinedBad) {
   char str[] = R"(
           OpCapability Shader
+          OpCapability Linkage
           OpMemoryModel Logical GLSL450
           OpName %missing "missing"
 %voidt  = OpTypeVoid
@@ -69,6 +71,7 @@ TEST_F(ValidateSSA, IdUndefinedBad) {
 TEST_F(ValidateSSA, IdRedefinedBad) {
   char str[] = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpMemoryModel Logical GLSL450
      OpName %2 "redefined"
 %1 = OpTypeVoid
@@ -85,6 +88,7 @@ TEST_F(ValidateSSA, IdRedefinedBad) {
 TEST_F(ValidateSSA, DominateUsageBad) {
   char str[] = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpMemoryModel Logical GLSL450
      OpName %1 "not_dominant"
 %2 = OpTypeFunction %1              ; uses %1 before it's definition
@@ -98,6 +102,7 @@ TEST_F(ValidateSSA, DominateUsageBad) {
 TEST_F(ValidateSSA, DominateUsageWithinBlockBad) {
   char str[] = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpMemoryModel Logical GLSL450
      OpName %bad "bad"
 %voidt = OpTypeVoid
@@ -120,6 +125,7 @@ TEST_F(ValidateSSA, DominateUsageWithinBlockBad) {
 TEST_F(ValidateSSA, DominateUsageSameInstructionBad) {
   char str[] = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpMemoryModel Logical GLSL450
      OpName %sum "sum"
 %voidt = OpTypeVoid
@@ -141,6 +147,7 @@ TEST_F(ValidateSSA, DominateUsageSameInstructionBad) {
 TEST_F(ValidateSSA, ForwardNameGood) {
   char str[] = R"(
      OpCapability Shader
+     OpCapability Linkage
      OpMemoryModel Logical GLSL450
      OpName %3 "main"
 %1 = OpTypeVoid
@@ -157,6 +164,7 @@ TEST_F(ValidateSSA, ForwardNameGood) {
 TEST_F(ValidateSSA, ForwardNameMissingTargetBad) {
   char str[] = R"(
       OpCapability Shader
+      OpCapability Linkage
       OpMemoryModel Logical GLSL450
       OpName %5 "main"              ; Target never defined
 )";
@@ -168,6 +176,7 @@ TEST_F(ValidateSSA, ForwardNameMissingTargetBad) {
 TEST_F(ValidateSSA, ForwardMemberNameGood) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
            OpMemberName %struct 0 "value"
            OpMemberName %struct 1 "size"
@@ -182,6 +191,7 @@ TEST_F(ValidateSSA, ForwardMemberNameGood) {
 TEST_F(ValidateSSA, ForwardMemberNameMissingTargetBad) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
            OpMemberName %struct 0 "value"
            OpMemberName %bad 1 "size"     ; Target is not defined
@@ -197,6 +207,7 @@ TEST_F(ValidateSSA, ForwardMemberNameMissingTargetBad) {
 TEST_F(ValidateSSA, ForwardDecorateGood) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
            OpDecorate %var Restrict
 %intt   =  OpTypeInt 32 1
@@ -210,6 +221,7 @@ TEST_F(ValidateSSA, ForwardDecorateGood) {
 TEST_F(ValidateSSA, ForwardDecorateInvalidIDBad) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
            OpName %missing "missing"
            OpDecorate %missing Restrict        ;Missing ID
@@ -231,6 +243,7 @@ TEST_F(ValidateSSA, ForwardDecorateInvalidIDBad) {
 TEST_F(ValidateSSA, ForwardMemberDecorateGood) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
            OpMemberDecorate %struct 1 RowMajor
 %intt   =  OpTypeInt 32 1
@@ -246,6 +259,7 @@ TEST_F(ValidateSSA, ForwardMemberDecorateGood) {
 TEST_F(ValidateSSA, ForwardMemberDecorateInvalidIdBad) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
            OpName %missing "missing"
            OpMemberDecorate %missing 1 RowMajor ; Target not defined
@@ -263,6 +277,7 @@ TEST_F(ValidateSSA, ForwardMemberDecorateInvalidIdBad) {
 TEST_F(ValidateSSA, ForwardGroupDecorateGood) {
   char str[] = R"(
           OpCapability Shader
+          OpCapability Linkage
           OpMemoryModel Logical GLSL450
           OpDecorate %dgrp RowMajor
 %dgrp   = OpDecorationGroup
@@ -280,6 +295,7 @@ TEST_F(ValidateSSA, ForwardGroupDecorateGood) {
 TEST_F(ValidateSSA, ForwardGroupDecorateMissingGroupBad) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
            OpName %missing "missing"
            OpDecorate %dgrp RowMajor
@@ -299,6 +315,7 @@ TEST_F(ValidateSSA, ForwardGroupDecorateMissingGroupBad) {
 TEST_F(ValidateSSA, ForwardGroupDecorateMissingTargetBad) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
            OpName %missing "missing"
            OpDecorate %dgrp RowMajor
@@ -318,6 +335,7 @@ TEST_F(ValidateSSA, ForwardGroupDecorateMissingTargetBad) {
 TEST_F(ValidateSSA, ForwardGroupDecorateDecorationGroupDominateBad) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
            OpName %dgrp "group"
            OpDecorate %dgrp RowMajor
@@ -337,6 +355,7 @@ TEST_F(ValidateSSA, ForwardGroupDecorateDecorationGroupDominateBad) {
 TEST_F(ValidateSSA, ForwardDecorateInvalidIdBad) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
            OpName %missing "missing"
            OpDecorate %missing Restrict        ; Missing target
@@ -358,6 +377,7 @@ TEST_F(ValidateSSA, ForwardDecorateInvalidIdBad) {
 TEST_F(ValidateSSA, FunctionCallGood) {
   char str[] = R"(
          OpCapability Shader
+         OpCapability Linkage
          OpMemoryModel Logical GLSL450
 %1    =  OpTypeVoid
 %2    =  OpTypeInt 32 1
@@ -385,6 +405,7 @@ TEST_F(ValidateSSA, FunctionCallGood) {
 TEST_F(ValidateSSA, ForwardFunctionCallGood) {
   char str[] = R"(
          OpCapability Shader
+         OpCapability Linkage
          OpMemoryModel Logical GLSL450
 %1    =  OpTypeVoid
 %2    =  OpTypeInt 32 1
@@ -412,6 +433,7 @@ TEST_F(ValidateSSA, ForwardFunctionCallGood) {
 TEST_F(ValidateSSA, ForwardBranchConditionalGood) {
   char str[] = R"(
             OpCapability Shader
+            OpCapability Linkage
             OpMemoryModel Logical GLSL450
 %voidt  =   OpTypeVoid
 %boolt  =   OpTypeBool
@@ -438,6 +460,7 @@ TEST_F(ValidateSSA, ForwardBranchConditionalGood) {
 TEST_F(ValidateSSA, ForwardBranchConditionalWithWeightsGood) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
 %voidt  =  OpTypeVoid
 %boolt  =  OpTypeBool
@@ -464,6 +487,7 @@ TEST_F(ValidateSSA, ForwardBranchConditionalWithWeightsGood) {
 TEST_F(ValidateSSA, ForwardBranchConditionalNonDominantConditionBad) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
            OpName %tcpy "conditional"
 %voidt  =  OpTypeVoid
@@ -493,6 +517,7 @@ TEST_F(ValidateSSA, ForwardBranchConditionalNonDominantConditionBad) {
 TEST_F(ValidateSSA, ForwardBranchConditionalMissingTargetBad) {
   char str[] = R"(
            OpCapability Shader
+           OpCapability Linkage
            OpMemoryModel Logical GLSL450
            OpName %missing "missing"
 %voidt  =  OpTypeVoid
@@ -521,6 +546,7 @@ TEST_F(ValidateSSA, ForwardBranchConditionalMissingTargetBad) {
 const string kHeader = R"(
 OpCapability Int8
 OpCapability DeviceEnqueue
+OpCapability Linkage
 OpMemoryModel Logical OpenCL
 )";
 
@@ -1346,6 +1372,7 @@ TEST_F(ValidateSSA, TypeForwardPointerForwardReference) {
   string str = R"(
                OpCapability Kernel
                OpCapability Addresses
+               OpCapability Linkage
                OpMemoryModel Logical OpenCL
                OpName %intptrt "intptrt"
                OpTypeForwardPointer %intptrt UniformConstant
@@ -1361,6 +1388,7 @@ TEST_F(ValidateSSA, TypeStructForwardReference) {
   string str = R"(
                OpCapability Kernel
                OpCapability Addresses
+               OpCapability Linkage
                OpMemoryModel Logical OpenCL
                OpName %structptr "structptr"
                OpTypeForwardPointer %structptr UniformConstant
index 653429f..d26a860 100644 (file)
@@ -28,6 +28,7 @@ namespace {
 TEST_F(ValidateStorage, FunctionStorageInsideFunction) {
   char str[] = R"(
           OpCapability Shader
+          OpCapability Linkage
           OpMemoryModel Logical GLSL450
 %intt   = OpTypeInt 32 1
 %voidt  = OpTypeVoid
@@ -47,6 +48,7 @@ TEST_F(ValidateStorage, FunctionStorageInsideFunction) {
 TEST_F(ValidateStorage, FunctionStorageOutsideFunction) {
   char str[] = R"(
           OpCapability Shader
+          OpCapability Linkage
           OpMemoryModel Logical GLSL450
 %intt   = OpTypeInt 32 1
 %voidt  = OpTypeVoid
@@ -68,6 +70,7 @@ TEST_F(ValidateStorage, OtherStorageOutsideFunction) {
           OpCapability Shader
           OpCapability Kernel
           OpCapability AtomicStorage
+          OpCapability Linkage
           OpMemoryModel Logical GLSL450
 %intt   = OpTypeInt 32 1
 %voidt  = OpTypeVoid
@@ -100,6 +103,7 @@ TEST_P(ValidateStorage, OtherStorageInsideFunction) {
           OpCapability Shader
           OpCapability Kernel
           OpCapability AtomicStorage
+          OpCapability Linkage
           OpMemoryModel Logical GLSL450
 %intt   = OpTypeInt 32 1
 %voidt  = OpTypeVoid
@@ -132,6 +136,7 @@ INSTANTIATE_TEST_CASE_P(MatrixOp, ValidateStorage,
 TEST_F(ValidateStorage, GenericVariableOutsideFunction) {
   const auto str = R"(
           OpCapability Kernel
+          OpCapability Linkage
           OpMemoryModel Logical OpenCL
 %intt   = OpTypeInt 32 1
 %ptrt   = OpTypePointer Function %intt
@@ -144,6 +149,7 @@ TEST_F(ValidateStorage, GenericVariableOutsideFunction) {
 TEST_F(ValidateStorage, GenericVariableInsideFunction) {
   const auto str = R"(
           OpCapability Shader
+          OpCapability Linkage
           OpMemoryModel Logical GLSL450
 %intt   = OpTypeInt 32 1
 %voidt  = OpTypeVoid