]> git.ipfire.org Git - thirdparty/vectorscan.git/commitdiff
rose: fix CHECK_NOT_HANDLED placement bug
authorJustin Viiret <justin.viiret@intel.com>
Fri, 27 May 2016 00:40:06 +0000 (10:40 +1000)
committerMatthew Barr <matthew.barr@intel.com>
Wed, 1 Jun 2016 00:56:52 +0000 (10:56 +1000)
The CHECK_NOT_HANDLED instruction was being inserted into an already
partially-flattened program, which would result in jump offsets becoming
incorrect.

This change places it as part of the normal flow of program
construction, which avoids this issue.

src/rose/rose_build_bytecode.cpp

index 30db15ffb6f524c76237fc9a9648bc4a73a131d6..1b00b4b5a1d4c8483905f36c13ac5b699c47a74c 100644 (file)
@@ -3019,6 +3019,25 @@ void makeRoleCheckBounds(const RoseBuildImpl &build, RoseVertex v,
     program.insert(it, ri);
 }
 
+static
+void makeRoleCheckNotHandled(build_context &bc, RoseVertex v,
+                             vector<RoseInstruction> &program) {
+    auto ri = RoseInstruction(ROSE_INSTR_CHECK_NOT_HANDLED,
+                              JumpTarget::NEXT_BLOCK);
+
+    u32 handled_key;
+    if (contains(bc.handledKeys, v)) {
+        handled_key = bc.handledKeys.at(v);
+    } else {
+        handled_key = verify_u32(bc.handledKeys.size());
+        bc.handledKeys.emplace(v, handled_key);
+    }
+
+    ri.u.checkNotHandled.key = handled_key;
+
+    program.push_back(move(ri));
+}
+
 static
 vector<RoseInstruction> makeProgram(RoseBuildImpl &build, build_context &bc,
                                     const RoseEdge &e) {
@@ -3042,6 +3061,13 @@ vector<RoseInstruction> makeProgram(RoseBuildImpl &build, build_context &bc,
         makeRoleCheckBounds(build, v, e, program);
     }
 
+    // This program may be triggered by different predecessors, with different
+    // offset bounds. We must ensure we put this check/set operation after the
+    // bounds check to deal with this case.
+    if (hasGreaterInDegree(1, v, g)) {
+        makeRoleCheckNotHandled(bc, v, program);
+    }
+
     makeRoleLookaround(build, bc, v, program);
     makeRoleCheckLeftfix(build, bc, v, program);
 
@@ -3228,48 +3254,6 @@ void buildLeftInfoTable(const RoseBuildImpl &tbi, build_context &bc,
     *laggedRoseCount = lagIndex;
 }
 
-static
-void makeRoleCheckNotHandled(build_context &bc, RoseVertex v,
-                             vector<RoseInstruction> &program) {
-    auto ri = RoseInstruction(ROSE_INSTR_CHECK_NOT_HANDLED,
-                              JumpTarget::NEXT_BLOCK);
-
-    u32 handled_key;
-    if (contains(bc.handledKeys, v)) {
-        handled_key = bc.handledKeys.at(v);
-    } else {
-        handled_key = verify_u32(bc.handledKeys.size());
-        bc.handledKeys.emplace(v, handled_key);
-    }
-
-    ri.u.checkNotHandled.key = handled_key;
-
-    // This program may be triggered by different predecessors, with different
-    // offset bounds. We must ensure we put this check/set operation after the
-    // bounds check to deal with this case.
-    auto it =
-        find_if(begin(program), end(program), [](const RoseInstruction &ri) {
-            return ri.code() > ROSE_INSTR_CHECK_BOUNDS;
-        });
-    program.insert(it, ri);
-}
-
-static
-vector<RoseInstruction> makePredProgram(RoseBuildImpl &build, build_context &bc,
-                                        const RoseEdge &e) {
-    const RoseGraph &g = build.g;
-    const RoseVertex v = target(e, g);
-
-    auto program = makeProgram(build, bc, e);
-
-    if (hasGreaterInDegree(1, v, g)) {
-        // Only necessary when there is more than one pred.
-        makeRoleCheckNotHandled(bc, v, program);
-    }
-
-    return program;
-}
-
 static
 u32 addPredBlocksSingle(
     map<u32, vector<vector<RoseInstruction>>> &predProgramLists,
@@ -3642,7 +3626,7 @@ u32 buildLiteralProgram(RoseBuildImpl &build, build_context &bc, u32 final_id,
                      g[target(e, g)].idx);
         assert(contains(bc.roleStateIndices, u));
         u32 pred_state = bc.roleStateIndices.at(u);
-        auto program = makePredProgram(build, bc, e);
+        auto program = makeProgram(build, bc, e);
         predProgramLists[pred_state].push_back(program);
     }