asil-1.2: src/InstrLocFilter.ag
-- Filters superfluous location instructions from the byte code
--
-- We keep branch targets and the location before a jump instruction
MODULE {InstrLocFilter} {instrLocFilter} {}
INCLUDE "ByteCodeAst.ag"
INCLUDE "ByteCodeLocationInfo.ag"
import
{
import Data.ByteString.Lazy(ByteString,pack)
import ByteCode
import Data.Word
import Data.Bits
import qualified Data.IntSet as IntSet
import Data.IntSet(IntSet)
import Data.Monoid
}
WRAPPER BodyInfo
{
-- | Computes the minimum length of an instruction (in bytes)
instrLocFilter :: BodyInfo -> BodyInfo
instrLocFilter body = body' where
inh = Inh_BodyInfo {}
sem = sem_BodyInfo body
syn = wrap_BodyInfo sem inh
body' = output_Syn_BodyInfo syn
}
ATTR BodyInfo Instructions Instruction CaseOffsets DebugType
Exceptions Exception AllTraits
[ | | output : SELF ]
SEM BodyInfo | Info
instructions.isBranch = True
instructions.revIsBranch = False
SEM Instructions | Cons
lhs.output = if @hd.skip then @tl.output else @hd.output : @tl.output
ATTR Instructions Instruction [ retain : IntSet | | ]
SEM BodyInfo | Info
instructions.retain = @instructions.locs `mappend` @exceptions.locs
ATTR Instruction [ | | skip : Bool ]
SEM Instruction | * - Location
lhs.skip = False
SEM Instruction | Location
lhs.skip = not (IntSet.member @index @lhs.retain)
-- Is the predecessor a branching instruction (except LookupSwitch)
ATTR Instructions Instruction [ | isBranch : Bool revIsBranch : Bool | ]
SEM Instruction
| * - IfEq IfFalse IfGe IfGt IfLe IfLt IfNGe IfNGt IfNLe IfNLt IfNe IfStrictEq IfStrictNe IfTrue Jump LookupSwitch
lhs.isBranch = False
lhs.revIsBranch = False
| IfEq IfFalse IfGe IfGt IfLe IfLt IfNGe IfNGt IfNLe IfNLt IfNe IfStrictEq IfStrictNe IfTrue Jump LookupSwitch
lhs.isBranch = True
lhs.revIsBranch = True
SEM Instructions | Cons -- reverse flow
tl.revIsBranch = @lhs.revIsBranch
hd.revIsBranch = @tl.revIsBranch
lhs.revIsBranch = @hd.revIsBranch
-- Compute the set of location to retain
ATTR Exceptions Exception Instructions Instruction CaseOffsets [ | | locs USE {`mappend`} {mempty} : IntSet ]
SEM Exception | Info
lhs.locs = IntSet.fromList $ map fromIntegral $ [@from,@to,@target]
-- Location following a branch target
SEM Instruction | Location
+locs = if @lhs.isBranch || @lhs.revIsBranch then (IntSet.insert @index) else id
SEM Instruction
| LookupSwitch IfEq IfFalse IfGe IfGt IfLe IfLt IfNGe IfNGt IfNLe IfNLt IfNe IfStrictEq IfStrictNe IfTrue Jump
+locs = IntSet.insert @loc.target
SEM CaseOffsets | Cons
+locs = IntSet.insert @loc.target
-- Slight hacks to deal with AG pecularities
SEM BodyInfo | Info
instructions.isBranch < instructions.revLocation
instructions.isBranch < instructions.revIsBranch