Fix ExtInst parsing: no IdRef* at end
authorDavid Neto <dneto@google.com>
Tue, 14 Jun 2016 20:41:27 +0000 (16:41 -0400)
committerDavid Neto <dneto@google.com>
Wed, 15 Jun 2016 14:00:06 +0000 (10:00 -0400)
The operands following the extended instruction literal
number are determined by the extended instruction itself.
So drop the zero-or-more IdRef pattern at the end of OpExtInst.

It's arguable whether this should actually be a grammar fix.  I've
chosen to patch this in SPIRV-Tools instead of in the grammar file.

Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/233

Also fix two test cases for OpenCL extended instructions.  These
errors of supplying too many operands are now detected.

test/BinaryParse.cpp
test/ExtInst.OpenCL.std.cpp
test/TextToBinary.Extension.cpp
utils/generate_grammar_tables.py

index ecffca9..e018752 100644 (file)
@@ -663,6 +663,13 @@ INSTANTIATE_TEST_CASE_P(
                       MakeInstruction(SpvOpExtInst, {2, 3, 100, 4, 5})}),
          "OpExtInst set Id 100 does not reference an OpExtInstImport result "
          "Id"},
+        {Concatenate({ExpectedHeaderForBound(101),
+                      MakeInstruction(SpvOpExtInstImport, {100},
+                                      MakeVector("OpenCL.std")),
+                      // OpenCL cos is #14
+                      MakeInstruction(SpvOpExtInst, {2, 3, 100, 14, 5, 999})}),
+         "Invalid instruction OpExtInst starting at word 10: expected no "
+         "more operands after 6 words, but stated word count is 7."},
         // In this case, the OpSwitch selector refers to an invalid ID.
         {Concatenate({ExpectedHeaderForBound(3),
                       MakeInstruction(SpvOpSwitch, {1, 2, 42, 3})}),
index b4ddaae..7c6e350 100644 (file)
@@ -233,8 +233,8 @@ INSTANTIATE_TEST_CASE_P(
         CASE1(Popcount, popcount),
         CASE3(SMad24, s_mad24),
         CASE3(UMad24, u_mad24),
-        CASE3(SMul24, s_mul24),
-        CASE3(UMul24, u_mul24), // enum value 170
+        CASE2(SMul24, s_mul24),
+        CASE2(UMul24, u_mul24), // enum value 170
         CASE1(UAbs, u_abs), // enum value 201
         CASE2(UAbs_diff, u_abs_diff),
         CASE2(UMul_hi, u_mul_hi),
index 18a91a8..7003608 100644 (file)
@@ -68,6 +68,12 @@ TEST_F(TextToBinaryTest, MultiImport) {
               Eq("Import Id is being defined a second time"));
 }
 
+TEST_F(TextToBinaryTest, TooManyArguments) {
+  const std::string input = R"(%opencl = OpExtInstImport "OpenCL.std"
+                               %2 = OpExtInst %float %opencl cos %x %oops")";
+  EXPECT_THAT(CompileFailure(input), Eq("Expected '=', found end of stream."));
+}
+
 TEST_F(TextToBinaryTest, ExtInstFromTwoDifferentImports) {
   const std::string input = R"(%1 = OpExtInstImport "OpenCL.std"
 %2 = OpExtInstImport "GLSL.std.450"
index 3c0b05e..f91f3ad 100755 (executable)
@@ -141,10 +141,26 @@ class InstInitializer(object):
         self.caps_mask = compose_capability_mask(caps)
         self.operands = [convert_operand_kind(o) for o in operands]
 
+        self.fix_syntax()
+
         operands = [o[0] for o in operands]
         self.ref_type_id = 'IdResultType' in operands
         self.def_result_id = 'IdResult' in operands
 
+
+    def fix_syntax(self):
+        """Fix an instruction's syntax, adjusting for differences between
+        the officially released grammar and how SPIRV-Tools uses the grammar.
+
+        Fixes:
+            - ExtInst should not end with SPV_OPERAND_VARIABLE_ID.
+            https://github.com/KhronosGroup/SPIRV-Tools/issues/233
+        """
+        if (self.opname == 'ExtInst'
+            and self.operands[-1] == 'SPV_OPERAND_TYPE_VARIABLE_ID'):
+           self.operands.pop()
+
+
     def __str__(self):
         template = ['{{"{opname}"', 'SpvOp{opname}', '{caps_mask}',
                     '{num_operands}', '{{{operands}}}',