From 9826522e34dcd2cfe584083cd67ad32307e18460 Mon Sep 17 00:00:00 2001 From: Justin Viiret Date: Fri, 27 May 2016 10:40:06 +1000 Subject: [PATCH] rose: fix CHECK_NOT_HANDLED placement bug 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 | 70 ++++++++++++-------------------- 1 file changed, 27 insertions(+), 43 deletions(-) diff --git a/src/rose/rose_build_bytecode.cpp b/src/rose/rose_build_bytecode.cpp index 30db15ff..1b00b4b5 100644 --- a/src/rose/rose_build_bytecode.cpp +++ b/src/rose/rose_build_bytecode.cpp @@ -3019,6 +3019,25 @@ void makeRoleCheckBounds(const RoseBuildImpl &build, RoseVertex v, program.insert(it, ri); } +static +void makeRoleCheckNotHandled(build_context &bc, RoseVertex v, + vector &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 makeProgram(RoseBuildImpl &build, build_context &bc, const RoseEdge &e) { @@ -3042,6 +3061,13 @@ vector 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 &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 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>> &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); }