P8IB      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ASafe%&BUsed at the type level to indicate a "closed" structure which supports control transfer only through the use of named labels---no "fallthrough" is permitted. The number of control-flow edges is unconstrained.CUsed at the type level to indicate an "open" structure with a unique, unnamed control-flow edge flowing in or out.  Fallthrough2 and concatenation are permitted at an open point.DEFGHIJKLMNOBCPQDEFGHIJKLMNOBCPQDEFGHIJKLMNOBCPQSafeDR1  !"#$%&'()*+,-./01  !"#$%&'()*+,-./0  !"#$%&'()*+,-./0SafeDR1"Obeys the following law: for all m 8 do { s <- checkpoint; m; restart s } == return () 123412341234 Safe234DR5RS6TU789V:W;<=>?XYZ[\]^_`abc 56789:;<=>?5RS6TU789V:W;<=>?XYZ[\]^_`abc SafeDRJrFind out how much fuel remains after a computation. Can be subtracted from initial fuel to get total consumption.@AdeBfgCDEFGHIJKLhijklmnopqrstu @ABCDEFGHIJKL@AdeBfgCDEFGHIJKLhijklmnopqrstu Safe234DRMNvOwPxQRSTUyz{ MNOPQRSTU MNvOwPxQRSTUyz{ Safe %&DORTV2A sequence of nodes. May be any of four shapes (OO, OC, CO, COC). Open at the entry means single entry, mutatis mutandis for exit. A closedclosed block is a basic/ block and can't be extended further. Clients should avoid manipulating blocks and should stick to either nodes or graphs._Dynamic shape valueb!Maybe type indexed by closed/opene!Maybe type indexed by open/closedh6Either type indexed by closed/open using type familiesiUsed at the type level to indicate a "closed" structure which supports control transfer only through the use of named labels---no "fallthrough" is permitted. The number of control-flow edges is unconstrained.j~Used at the type level to indicate an "open" structure with a unique, unnamed control-flow edge flowing in or out.  Fallthrough2 and concatenation are permitted at an open point.xLSplit a closed block into its entry node, open middle block, and exit node.|}Convert a list of nodes to a block. The entry and exit node must or must not be present depending on the shape of the block.#map a function over the nodes of a V A strict map over a block, with different functions to apply to first nodes, middle nodes and last nodes respectively. The map is strict.Fold a function over every node in a block, forward or backward. The fold function must be polymorphic in the shape of the nodes.A block is "front biased" if the left child of every concatenation operation is a node, not a general block; a front-biased block is analogous to an ordinary list. If a block is front-biased, then its nodes can be traversed from front to back without general recusion; tail recursion suffices. Not all shapes can be front-biased; a closed/open block is inherently back-biased.xA block is "back biased" if the right child of every concatenation operation is a node, not a general block; a back-biased block is analogous to a snoc-list. If a block is back-biased, then its nodes can be traversed from back to back without general recusion; tail recursion suffices. Not all shapes can be back-biased; an open/closed block is inherently front-biased.5VWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~|}~2VWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'VWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~|}~ Safe %&9;DORT UGives access to the anchor points for nonlocal edges as well as the edges themselvesGraph' is abstracted over the block type, so that we can build graphs of annotated blocks for example (Compiler.Hoopl.Dataflow needs this).@A control-flow graph, which may take any of four shapes (O/O, OC, CO, C/C). A graph open at the entry has a single, distinguished, anonymous entry point; if a graph is closed at the entry, its entry point(s) are supplied by a context.Body abstracted over block5A (possibly empty) collection of closed/closed blocksMaps over all nodes in a graph. Function  enables a change of representation of blocks, nodes, or both. It lifts a polymorphic block transform into a polymorphic graph transform. When the block representation stabilizes, a similar function should be provided for blocks.mFold a function over every node in a graph. The fold function must be polymorphic in the shape of the nodes.(This is the most important traversal over this data structure. It drops unreachable code and puts blocks in an order that is good for solving forward dataflow problems quickly. The reverse order is good for solving backward dataflow problems quickly. The forward order is also reasonably good for emitting instructions, except that it will not usually exploit Forrest Baskett's trick of eliminating the unconditional branch from a loop. For that you would need a more serious analysis, probably based on dominators, to identify loop headers.The ubiquity of ' is one reason for the ubiquity of the LGraph3 representation, when for most purposes the plain W representation is more mathematically elegant (but results in more complicated code).+Here's an easy way to go wrong! Consider  A -> [B,C] B -> D C -> D c Then ordinary dfs would give [A,B,D,C] which has a back ref from C to D. Better to get [A,B,C,D] Traversal:  returns a list of blocks reachable from the entry of enterable graph. The entry and exit are *not* included. The list has the following property:iSay a "back reference" exists if one of a block's control-flow successors precedes it in the output list1Then there are as few back references as possibletThe output is suitable for use in a forward dataflow problem. For a backward problem, simply reverse the list. (u is sufficiently tricky to implement that one doesn't want to try and maintain both forward and backward versions.)7'/Safe %&<=DORT block decorated with factA transfer function might want to use the logging flag to control debugging, as in for example, it updates just one element in a big finite map. We don't want Hoopl to show the whole fact, and only the transfer function knows exactly what changed. creates a M from a list of (PZ, fact) pairs. If the same label appears more than once, the relevant facts are joined.Functions passed to A should not be aware of the fuel supply. The result returned by  respects fuel.Functions passed to A should not be aware of the fuel supply. The result returned by  respects fuel.vif the graph being analyzed is open at the entry, there must be no other entry point, or all goes horribly wrong...Functions passed to A should not be aware of the fuel supply. The result returned by  respects fuel.Functions passed to A should not be aware of the fuel supply. The result returned by  respects fuel.uif the graph being analyzed is open at the exit, I don't quite understand the implications of possible other exitsZwThis argument may assume that any function passed to it respects fuel, and it must return a result that respects fuel.wThis argument may assume that any function passed to it respects fuel, and it must return a result that respects fuel.wThis argument may assume that any function passed to it respects fuel, and it must return a result that respects fuel.wThis argument may assume that any function passed to it respects fuel, and it must return a result that respects fuel.67Safe%&NOTFunction inspired by rew in the paperFunction inspired by add in the paperFunction inspired by add in the paper SafeSafe%&OTMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~jiefgbcdh_`aVWXYZ[\]^klmnopq|rstuvwxy}~z{PQSONMTURQSafe %&9;OT6Translate a high-level if-then-else construct into an . The condition takes as arguments labels on the true-false branch and returns a single-entry, two-exit graph which exits to the two labels.For some graph-construction operations and some optimizations, Hoopl must be able to create control-flow edges using a given node type n.8Create a branch node, the source of a control-flow edge.ECreate a label node, the target (destination) of a control-flow edge.The LabelsB class defines things that can be lambda-bound by an argument to withFreshLabels.. Such an argument may lambda-bind a single P, or if multiple labels are needed, it can bind a tuple. Tuples can be nested, so arbitrarily many fresh labels can be acquired in a single call.)For example usage see implementations of  and .sThe type of abstract graphs. Offers extra "smart constructors" that may consume fresh labels during construction.Take an abstract $ and make a concrete (if monadic) .vAs noted in the paper, we can define a single, polymorphic type of splicing operation with the very polymorphic type 0 AGraph n e a -> AGraph n a x -> AGraph n e x / However, we feel that this operation is a bit too polymorphic, and that it's too easy for clients to use it blindly without thinking. We therfore split it into two operations,  and -, which are supplemented by other functions:The v operator is true concatenation, for connecting open graphs. Control flows from the left graph to the right graph.The  operator splices together two graphs at a closed point. Nothing is known about control flow. The vertical bar stands for "closed point" just as the angle brackets above stand for "open point". Unlike the  * operator, the |*><*| can create a control-flow graph with dangling outedges or unreachable blocks. The operator must be used carefully, so we have chosen a long name on purpose, to help call people's attention to what they're doing. The operator @ adds a set of basic blocks (represented as a closed/closed  to an existing graph, without changing the shape of the existing graph. In some cases, it's necessary to introduce a branch and a label to 'get around' the blocks added, so this operator, and other functions based on it, requires a F type-class constraint and is available only on AGraph, not Graph.yWe have discussed a dynamic assertion about dangling outedges and unreachable blocks, but nothing is implemented yet.WAn empty graph that is open at entry and exit. It is the left and right identity of .YAn empty graph that is closed at entry and exit. It is the left and right identity of . Create a graph from a first node!Create a graph from a middle nodeCreate a graph from a last node9Concatenate two graphs; control flows from left to right.SSplice together two graphs at a closed point; nothing is known about control flow.>Conveniently concatenate a sequence of open/open graphs using .#Create a graph that defines a label'Create a graph that branches to a labelPConveniently concatenate a sequence of middle nodes to form an open/open graph.0Create a graph containing only an entry sequence/Create a graph containing only an exit sequence"Take a graph and make it abstract. Lifts binary  functions into  functions.Extend an existing l with extra basic blocks "out of line". No control flow is implied. Simon PJ should give example use case.(loop conditionbody of the loopthe final while loop       32Safe%&T Type a& with top and bottom elements adjoined Type a with a top element adjoined Type a with a bottom element adjoined0Adds top, bottom, or both to help form a latticeThe type parameters t and bU are used to say whether top and bottom elements have been added. The analogy with V is nearly exact:A VB is closed at the entry if and only if it has a first node; a : is closed at the top if and only if it has a top element.A V@ is closed at the exit if and only if it has a last node; a @ is closed at the bottom if and only if it has a bottom element.AWe thus have four possible types, of which three are interesting:  Pointed C C aType a, extended with both top and bottom elements. Pointed C O aType a1 extended with a top element only. (Presumably a2 comes equipped with a bottom element of its own.) Pointed O C aType a& extended with a bottom element only.  Pointed O O aIsomorphic to a , and therefore not interesting.AThe advantage of all this GADT-ishness is that the constructors , , and ! can all be used polymorphically.'A 'Pointed t b' type is an instance of  and .Given a join function and a name, creates a semi lattice by adding a bottom element, and possibly a top element also. A specialized version of ..A more general case for creating a new latticeGiven a join function and a name, creates a semi lattice by adding a top element but no bottom element. Caller must supply the bottom element..A more general case for creating a new lattice          Safe%&:OTSafe%&:OTDebugging combinators: Each combinator takes a dataflow pass and produces a dataflow pass that can output debugging messages. You provide the function, we call it with the applicable message.(The most common use case is probably to: import pass trace, as the 1st argument to the debug combinator=pass 'const true' as the 2nd argument to the debug combinatorThere are two kinds of debugging messages for a join, depending on whether the join is higher in the lattice than the old fact: 1. If the join is higher, we show: + JoinL: f1 join f2 = f' where: + indicates a change L is the label where the join takes place f1 is the old fact at the label f2 is the new fact we are joining to f1 f' is the result of the join 2. _ JoinL: f2 <= f1 where: _ indicates no change L is the label where the join takes place f1 is the old fact at the label (which remains unchanged) f2 is the new fact we joined with f1  Safe %&DORT  Forward dataflow analysis and rewriting for the special case of a Body. A set of entry points must be supplied; blocks not reachable from the set are thrown away.!Backward dataflow analysis and rewriting for the special case of a Body. A set of entry points must be supplied; blocks not reachable from the set are thrown away.#Internal utility; should not escapeJA value that can be used for the entry point of a graph open at the entry."Forward dataflow analysis and rewriting for the special case of a graph open at the entry. This special case relieves the client from having to specify a type signature for gH, which beginners might find confusing and experts might find annoying.#Backward dataflow analysis and rewriting for the special case of a graph open at the entry. This special case relieves the client from having to specify a type signature for gH, which beginners might find confusing and experts might find annoying.$A utility function so that a transfer function for a first node can be given just a fact; we handle the lookup. This function is planned to be made obsolete by changes in the dataflow interface.%This utility function handles a common case in which a transfer function produces a single fact out of a last node, which is then distributed over the outgoing edges.&This utility function handles a common case in which a transfer function for a last node takes the incoming fact unchanged and simply distributes that fact over the outgoing edges.'This utility function handles a common case in which a backward transfer function takes the incoming fact unchanged and tags it with the node's label.(=List of (unlabelled) facts from the successors of a last node)Join a list of facts.+It's common to represent dataflow facts as a map from variables to some fact about the locations. For these maps, the join operation on the map can be expressed in terms of the join on each element of the codomain: !"#$%&'()*+  !"#$%&'()*+ !"#$%&'()*+Safe!  !"#$%&'()*+,-./0123456789:;=>?@ABCDEFGJLMNOPSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+.jiefgbcdh_`aVWXYZ[\]^klmnopq|rstuvwxy}~z{  $%&'()*+ !"# !"#$%&'()*+,- ./01234PQSONMTURQ   CLJKGHIDEFBA@;=:9786>5?<Safe%&,7List of labels, extended with a standard bottom element-The fact that goes into the entry of a dominator analysis: the first node is dominated only by the entry point, which is represented by the empty list of labels./Dominator pass,-./,-./,-./,-./Safe%&0This data structure is a *rose tree* in which each node may have arbitrarily many children. Each node dominates all its descendants.6represents part of the domination relation: each label in a list is dominated by all its successors. This is a newtype only so we can give it a fancy Show instance.77List of labels, extended with a standard bottom element8The fact that goes into the entry of a dominator analysis: the first node is dominated only by the entry point, which is represented by the empty list of labels.<Dominator pass=AMap from a FactBase for dominator lists into a dominator tree. Given a dominator tree, produce a string representation, in the input language of dot, that will enable dot to produce a visualization of the tree. For more info about dot see  http://www.graphviz.org.>mTakes FactBase from dominator analysis and returns a map from each label to its immediate dominator, if any0123456789:;<=>?@A0123456789:;<=>75698;:23401=><0123456789:;<=>?@A !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGG>?HI@AJKLMNOPQRvSTUVWXYZ[ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~    g                      %hoopl-3.10.2.2-HUR2yor3e6ADMFRCIsdOulCompiler.HooplCompiler.Hoopl.InternalsCompiler.Hoopl.WrappersCompiler.Hoopl.Passes.DListCompiler.Hoopl.Passes.DominatorCompiler.Hoopl.ShapeCompiler.Hoopl.CollectionsCompiler.Hoopl.CheckpointCompiler.Hoopl.UniqueCompiler.Hoopl.FuelCompiler.Hoopl.LabelCompiler.Hoopl.BlockCompiler.Hoopl.GraphCompiler.Hoopl.DataflowCompiler.Hoopl.CombinatorsCompiler.Hoopl.MkGraphCompiler.Hoopl.PointedCompiler.Hoopl.ShowCompiler.Hoopl.DebugDebugTraceCompiler.Hoopl.XUtilIsMapKeyOfmapNullmapSize mapMember mapLookupmapFindWithDefaultmapEmpty mapSingleton mapInsert mapInsertWith mapDeletemapUnionmapUnionWithKey mapDifferencemapIntersection mapIsSubmapOfmapMap mapMapWithKeymapFoldmapFoldWithKey mapFiltermapElemsmapKeys mapToList mapFromListmapFromListWithIsSetElemOfsetNullsetSize setMembersetEmpty setSingleton setInsert setDeletesetUnion setDifferencesetIntersection setIsSubsetOfsetFoldsetElems setFromList setInsertList setDeleteList setUnions mapInsertList mapDeleteList mapUnionsCheckpointMonad Checkpoint checkpointrestart UniqueMonadTSimpleUniqueMonad UniqueMonad freshUnique UniqueMap UniqueSetUnique uniqueToInt intToUniquerunSimpleUniqueMonadrunUniqueMonadTSimpleFuelMonadInfiniteFuelMonadCheckingFuelMonadFuel FuelMonadT runWithFuelliftFuel FuelMonadgetFuelsetFuel fuelRemainingwithFuel infiniteFuelFactBaseLabelMapLabelSetLabel lblToUnique uniqueToLbl freshLabelnoFacts lookupFactBlockBlockCOBlockCCBlockOCBNilBMiddleBCatBSnocBConsShapeClosedOpenMaybeCJustCNothingCMaybeOJustONothingO IndexedCOCO isEmptyBlock emptyBlock blockCons blockSnoc blockJoinHead blockJoinTail blockJoin blockAppend firstNodelastNodeendNodesblockSplitHeadblockSplitTail blockSplit blockSplitAny blockToList blockFromList blockJoinAnyreplaceFirstNodereplaceLastNodemapBlock mapBlock' mapBlock3'foldBlockNodesF3foldBlockNodesFfoldBlockNodesB3foldBlockNodesBfrontBiasBlock backBiasBlock LabelsPtr targetLabelsNonLocal entryLabel successorsGraph'GNilGUnitGManyGraphBody'Body emptyBody bodyUnionbodyListaddBlock bodyGraphgUnitOOgUnitOCgUnitCOgUnitCCcatGraphNodeOOcatGraphNodeOCcatNodeOOGraphcatNodeCOGraph blockGraphsplicegSplicemapGraphmapGraphBlocksfoldGraphNodes postorder_dfs preorder_dfspostorder_dfs_from_exceptpostorder_dfs_frompreorder_dfs_from_except labelsDefined labelsUsedexternalEntryLabels BwdRewrite BwdRewrite3 getBRewrite3 BwdTransfer BwdTransfer3 getBTransfer3BwdPass bp_lattice bp_transfer bp_rewriteFact FwdRewrite FwdRewrite3 getFRewrite3 FwdTransfer FwdTransfer3 getFTransfer3FwdPass fp_lattice fp_transfer fp_rewrite ChangeFlagNoChange SomeChangeNewFactOldFactJoinFunDataflowLattice fact_namefact_bot fact_joinchangeIf mkFactBasewrapFRwrapFR2 mkFTransfer3 mkFTransfer mkFRewrite3 noFwdRewrite mkFRewriteanalyzeAndRewriteFwdwrapBRwrapBR2 mkBTransfer3 mkBTransfer mkBRewrite3 noBwdRewrite mkBRewriteanalyzeAndRewriteBwd deepFwdRw3 deepFwdRw thenFwdRw iterFwdRw deepBwdRw3 deepBwdRw thenBwdRw iterBwdRwpairFwdpairBwd pairLatticeIfThenElseable mkIfThenElse HooplNode mkBranchNode mkLabelNode withFreshAGraph graphOfAGraph emptyGraphemptyClosedGraphmkFirstmkMiddlemkLast<*>|*><*| catGraphsmkLabelmkBranch mkMiddlesmkEntrymkExit aGraphOfGraph addBlocks mkWhileDo addEntrySeq addExitSeq unionBlocks WithTopAndBotWithTopWithBotPointedBotPElemTop addPoints addPoints'extendJoinDomain liftJoinTopaddTopaddTop'Showing showGraph showFactBaseTraceFn debugFwdJoins debugBwdJoinsdebugFwdTransfersdebugBwdTransfersanalyzeAndRewriteFwdBodyanalyzeAndRewriteBwdBodyanalyzeAndRewriteFwdOxanalyzeAndRewriteBwdOx firstXferdistributeXferdistributeFactdistributeFactBwdsuccessorFacts joinFacts joinOutFactsjoinMapsDomsdomEntry domLatticedomPass DominatorTree Dominates DominatorNodeEntryLabelledDPathdomPath extendDomtreeimmediateDominators$fShowDominatorNode$fShowDominatorTree $fShowDPathShapelyshape shapeAtEntry shapeAtExitShapeOOShapeCOShapeOCShapeCC HalfShapeShapeOShapeCentryHalfShape exitHalfShapeUMTunUMTSUMunSUMUMUS allUniques$fUniqueMonadUniqueMonadT$fMonadUniqueMonadT$fApplicativeUniqueMonadT$fFunctorUniqueMonadT"$fCheckpointMonadSimpleUniqueMonad$fUniqueMonadSimpleUniqueMonad$fMonadSimpleUniqueMonad$fApplicativeSimpleUniqueMonad$fFunctorSimpleUniqueMonad$fIsMapUniqueMap$fIsSetUniqueSetIFMunIFMFMunFM$fFuelMonadTInfiniteFuelMonad"$fCheckpointMonadInfiniteFuelMonad$fFuelMonadInfiniteFuelMonad$fUniqueMonadInfiniteFuelMonad$fMonadInfiniteFuelMonad$fApplicativeInfiniteFuelMonad$fFunctorInfiniteFuelMonad$fFuelMonadTCheckingFuelMonad$fFuelMonadCheckingFuelMonad$fUniqueMonadCheckingFuelMonad"$fCheckpointMonadCheckingFuelMonad$fMonadCheckingFuelMonad$fApplicativeCheckingFuelMonad$fFunctorCheckingFuelMonadLMLS$fIsMapLabelMap$fIsSetLabelSet $fShowLabelcat$fFunctorMaybeC$fFunctorMaybeOgraphDfsHLVMunVMmarkedmarkcons $fMonadVM$fApplicativeVM $fFunctorVM $fLabelsPtr[]$fLabelsPtrLabelSet$fLabelsPtrLabel $fLabelsPtrn$fNonLocalBlockDBlock ShapeLifter singletonDG fwdEntryFact fwdEntryLabel ftransferfrewrite bwdEntryFact btransferbrewriteDG DirectionFwdBwdEntries noRewritedistinguishedExitFactarfGraph joinInFactsforwardBlockListarbGraphbackwardBlockListdistinguishedEntryFact updateFactfixpointnormalizeGraphdgnildgnilCdgSplicegetFact$fShapeLifterOC$fShapeLifterOO$fShapeLifterCO$fNonLocalDBlock _frewrite_cpsfadd_rwbadd_rwUniquesGraphRepliftA2A$fUniques(,,,) $fUniques(,,) $fUniques(,)$fIfThenElseableC$fIfThenElseableO$fUniquesLabel $fUniquesInt$fGraphRepAGraph$fGraphRepGraph'baseGHC.BaseFunctorGHC.ShowShow $fOrdPointed $fEqPointed$fFunctorPointed $fShowPointedopenBPredFPredShowN ChangePred debugJoins mapBodyFacts noEntriesextendtree2dot