Simplify (and test) the alternate-parsing pattern.
authorDejan Mircevski <deki@google.com>
Tue, 29 Sep 2015 14:38:18 +0000 (10:38 -0400)
committerDavid Neto <dneto@google.com>
Mon, 26 Oct 2015 16:55:33 +0000 (12:55 -0400)
source/operand.cpp
source/operand.h
source/text.cpp
test/OperandPattern.cpp

index 24d484f..27bd545 100644 (file)
@@ -1610,22 +1610,17 @@ spv_operand_type_t spvTakeFirstMatchableOperand(
   return result;
 }
 
-void spvSwitchToAlternateParsingAfterImmediate(
-    spv_operand_pattern_t* pExpectedOperands) {
-  if (pExpectedOperands->empty()) {
-    pExpectedOperands->push_back(SPV_OPERAND_TYPE_OPTIONAL_CIV);
-  } else if (pExpectedOperands->size() == 1 &&
-             (*pExpectedOperands)[0] == SPV_OPERAND_TYPE_RESULT_ID) {
-    // Must preserve the result-id position.
-    pExpectedOperands->push_back(SPV_OPERAND_TYPE_OPTIONAL_CIV);
-  } else {
-    // Must preserve the result-id position.
-    for (auto& operand : *pExpectedOperands) {
-      if (operand != SPV_OPERAND_TYPE_RESULT_ID) {
-        // This may end up inserting multiple SPV_OPERAND_TYPE_OPTIONAL_CIVs,
-        // but that's OK because it's an optional type.
-        operand = SPV_OPERAND_TYPE_OPTIONAL_CIV;
-      }
+spv_operand_pattern_t spvAlternatePatternFollowingImmediate(
+    const spv_operand_pattern_t& pattern) {
+  spv_operand_pattern_t alternatePattern;
+  for (const auto& operand : pattern) {
+    if (operand == SPV_OPERAND_TYPE_RESULT_ID) {
+      alternatePattern.push_back(operand);
+      alternatePattern.push_back(SPV_OPERAND_TYPE_OPTIONAL_CIV);
+      return alternatePattern;
     }
+    alternatePattern.push_back(SPV_OPERAND_TYPE_OPTIONAL_CIV);
   }
+  // No result-id found, so just expect CIVs.
+  return {SPV_OPERAND_TYPE_OPTIONAL_CIV};
 }
index eb8615e..5e6f51f 100644 (file)
@@ -152,9 +152,9 @@ bool spvExpandOperandSequenceOnce(spv_operand_type_t type,
 /// operand type.
 spv_operand_type_t spvTakeFirstMatchableOperand(spv_operand_pattern_t* pattern);
 
-/// Switches *pExpectedOperands to the post-immediate alternate pattern, which
-/// allows a limited set of operand types.
-void spvSwitchToAlternateParsingAfterImmediate(
-    spv_operand_pattern_t* pExpectedOperands);
+/// Calculates the corresponding post-immediate alternate pattern, which allows
+/// a limited set of operand types.
+spv_operand_pattern_t spvAlternatePatternFollowingImmediate(
+    const spv_operand_pattern_t& pattern);
 
 #endif
index 87b479a..5bc0b5d 100644 (file)
@@ -182,7 +182,8 @@ spv_result_t spvTextEncodeOperand(const libspirv::AssemblyGrammar &grammar,
     context->seekForward(size);
     pInst->words[pInst->wordCount] = immediateInt;
     pInst->wordCount += 1;
-    spvSwitchToAlternateParsingAfterImmediate(pExpectedOperands);
+    *pExpectedOperands =
+        spvAlternatePatternFollowingImmediate(*pExpectedOperands);
     return SPV_SUCCESS;
   }
 
index 6fc9df3..adf526a 100644 (file)
@@ -83,13 +83,16 @@ TEST_P(MaskExpansionTest, Sample) {
   ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
 
   spv_operand_pattern_t pattern(GetParam().initial);
-  spvPrependOperandTypesForMask(operandTable, GetParam().type, GetParam().mask, &pattern);
+  spvPrependOperandTypesForMask(operandTable, GetParam().type, GetParam().mask,
+                                &pattern);
   EXPECT_THAT(pattern, Eq(GetParam().expected));
 }
 
 // These macros let us write non-trivial examples without too much text.
-#define SUFFIX0  SPV_OPERAND_TYPE_NONE, SPV_OPERAND_TYPE_ID
-#define SUFFIX1  SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE, SPV_OPERAND_TYPE_STORAGE_CLASS
+#define SUFFIX0 SPV_OPERAND_TYPE_NONE, SPV_OPERAND_TYPE_ID
+#define SUFFIX1                                              \
+  SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE, \
+      SPV_OPERAND_TYPE_STORAGE_CLASS
 INSTANTIATE_TEST_CASE_P(
     OperandPattern, MaskExpansionTest,
     ::testing::ValuesIn(std::vector<MaskExpansionCase>{
@@ -112,7 +115,7 @@ INSTANTIATE_TEST_CASE_P(
          {SPV_OPERAND_TYPE_LITERAL_NUMBER, SUFFIX1}},
         // Volatile with Aligned still has just one literal number operand.
         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
-         spv::MemoryAccessVolatileMask| spv::MemoryAccessAlignedMask,
+         spv::MemoryAccessVolatileMask | spv::MemoryAccessAlignedMask,
          {SUFFIX1},
          {SPV_OPERAND_TYPE_LITERAL_NUMBER, SUFFIX1}},
     }));
@@ -165,4 +168,111 @@ INSTANTIATE_TEST_CASE_P(NonMatchableOperandExpansion,
                         VariableOperandExpansionTest,
                         ::testing::ValuesIn(allOperandTypes()));
 
+TEST(AlternatePatternFollowingImmediate, Empty) {
+  EXPECT_THAT(spvAlternatePatternFollowingImmediate({}),
+              Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+}
+
+TEST(AlternatePatternFollowingImmediate, SingleElement) {
+  // Spot-check a random selection of types.
+  EXPECT_THAT(spvAlternatePatternFollowingImmediate(
+                  {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_NUMBER}),
+              Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+  EXPECT_THAT(
+      spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_CAPABILITY}),
+      Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+  EXPECT_THAT(
+      spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_LOOP_CONTROL}),
+      Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+  EXPECT_THAT(spvAlternatePatternFollowingImmediate(
+                  {SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER}),
+              Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+  EXPECT_THAT(spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_ID}),
+              Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+  EXPECT_THAT(spvAlternatePatternFollowingImmediate(
+                  {SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE}),
+              Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+}
+
+TEST(AlternatePatternFollowingImmediate, SingleResultId) {
+  EXPECT_THAT(
+      spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_RESULT_ID}),
+      Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_RESULT_ID,
+                               SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+}
+
+TEST(AlternatePatternFollowingImmediate, MultipleNonResultIds) {
+  EXPECT_THAT(
+      spvAlternatePatternFollowingImmediate(
+          {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_NUMBER,
+           SPV_OPERAND_TYPE_CAPABILITY, SPV_OPERAND_TYPE_LOOP_CONTROL,
+           SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER, SPV_OPERAND_TYPE_ID,
+           SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE}),
+      Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+}
+
+TEST(AlternatePatternFollowingImmediate, ResultIdFront) {
+  EXPECT_THAT(spvAlternatePatternFollowingImmediate(
+                  {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}),
+              Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_RESULT_ID,
+                                       SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+  EXPECT_THAT(spvAlternatePatternFollowingImmediate(
+                  {SPV_OPERAND_TYPE_RESULT_ID,
+                   SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID}),
+              Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_RESULT_ID,
+                                       SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+  EXPECT_THAT(spvAlternatePatternFollowingImmediate(
+                  {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_DIMENSIONALITY,
+                   SPV_OPERAND_TYPE_LINKAGE_TYPE,
+                   SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
+                   SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
+                   SPV_OPERAND_TYPE_VARIABLE_ID}),
+              Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_RESULT_ID,
+                                       SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+}
+
+TEST(AlternatePatternFollowingImmediate, ResultIdMiddle) {
+  EXPECT_THAT(spvAlternatePatternFollowingImmediate(
+                  {SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
+                   SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}),
+              Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
+                                       SPV_OPERAND_TYPE_RESULT_ID,
+                                       SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+  EXPECT_THAT(
+      spvAlternatePatternFollowingImmediate(
+          {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE,
+           SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
+           SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
+           SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}),
+      Eq(spv_operand_pattern_t{
+          SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
+          SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
+          SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+}
+
+TEST(AlternatePatternFollowingImmediate, ResultIdBack) {
+  EXPECT_THAT(spvAlternatePatternFollowingImmediate(
+                  {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}),
+              Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
+                                       SPV_OPERAND_TYPE_RESULT_ID,
+                                       SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+  EXPECT_THAT(spvAlternatePatternFollowingImmediate(
+                  {SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
+                   SPV_OPERAND_TYPE_RESULT_ID}),
+              Eq(spv_operand_pattern_t{
+                  SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
+                  SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+  EXPECT_THAT(
+      spvAlternatePatternFollowingImmediate(
+          {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE,
+           SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
+           SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
+           SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_RESULT_ID}),
+      Eq(spv_operand_pattern_t{
+          SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
+          SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
+          SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
+          SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_OPTIONAL_CIV}));
+}
+
 }  // anonymous namespace