@@ -15,6 +15,43 @@ private class OldInstruction = Reachability::ReachableInstruction;
1515
1616import Cached
1717
18+ /**
19+ * Holds if `instruction` is the first instruction that may be followed by
20+ * an `InitializeGroup` instruction, and the enclosing function of
21+ * `instruction` is `func`.
22+ */
23+ private predicate isFirstInstructionBeforeInitializeGroup ( Instruction instruction , IRFunction func ) {
24+ instruction = getChi ( any ( OldIR:: InitializeNonLocalInstruction init ) ) and
25+ func = instruction .getEnclosingIRFunction ( )
26+ }
27+
28+ /** Gets the `i`'th `InitializeGroup` instruction in `func`. */
29+ private InitializeGroupInstruction getInitGroupInstruction ( int i , IRFunction func ) {
30+ exists ( Alias:: VariableGroup vg |
31+ vg .getIRFunction ( ) = func and
32+ vg .getInitializationOrder ( ) = i and
33+ result = initializeGroup ( vg )
34+ )
35+ }
36+
37+ /**
38+ * Holds if `instruction` is the last instruction in the chain of `InitializeGroup`
39+ * instructions in `func`. The chain of instructions may be empty in which case
40+ * `instruction` satisfies
41+ * ```
42+ * isFirstInstructionBeforeInitializeGroup(instruction, func)
43+ * ```
44+ */
45+ predicate isLastInstructionForInitializeGroups ( Instruction instruction , IRFunction func ) {
46+ exists ( int i |
47+ instruction = getInitGroupInstruction ( i , func ) and
48+ not exists ( getInitGroupInstruction ( i + 1 , func ) )
49+ )
50+ or
51+ isFirstInstructionBeforeInitializeGroup ( instruction , func ) and
52+ not exists ( getInitGroupInstruction ( 0 , func ) )
53+ }
54+
1855cached
1956private module Cached {
2057 cached
@@ -356,14 +393,28 @@ private module Cached {
356393 )
357394 }
358395
359- /*
360- * This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
361- * that node is its successor in the new successor relation, and the Chi node's successors are
362- * the new instructions generated from the successors of the old instruction
363- */
396+ private InitializeGroupInstruction firstInstructionToInitializeGroup (
397+ Instruction instruction , EdgeKind kind
398+ ) {
399+ exists ( IRFunction func |
400+ isFirstInstructionBeforeInitializeGroup ( instruction , func ) and
401+ result = getInitGroupInstruction ( 0 , func ) and
402+ kind instanceof GotoEdge
403+ )
404+ }
364405
365- cached
366- Instruction getInstructionSuccessor ( Instruction instruction , EdgeKind kind ) {
406+ private Instruction getNextInitializeGroupInstruction ( Instruction instruction , EdgeKind kind ) {
407+ exists ( int i , IRFunction func |
408+ func = instruction .getEnclosingIRFunction ( ) and
409+ instruction = getInitGroupInstruction ( i , func ) and
410+ result = getInitGroupInstruction ( i + 1 , func ) and
411+ kind instanceof GotoEdge
412+ )
413+ }
414+
415+ private Instruction getInstructionSuccessorAfterInitializeGroup0 (
416+ Instruction instruction , EdgeKind kind
417+ ) {
367418 if hasChiNode ( _, getOldInstruction ( instruction ) )
368419 then
369420 result = getChi ( getOldInstruction ( instruction ) ) and
@@ -383,6 +434,35 @@ private module Cached {
383434 )
384435 }
385436
437+ private Instruction getInstructionSuccessorAfterInitializeGroup (
438+ Instruction instruction , EdgeKind kind
439+ ) {
440+ exists ( IRFunction func , Instruction firstBeforeInitializeGroup |
441+ isLastInstructionForInitializeGroups ( instruction , func ) and
442+ isFirstInstructionBeforeInitializeGroup ( firstBeforeInitializeGroup , func ) and
443+ result = getInstructionSuccessorAfterInitializeGroup0 ( firstBeforeInitializeGroup , kind )
444+ )
445+ }
446+
447+ /**
448+ * This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
449+ * that node is its successor in the new successor relation, and the Chi node's successors are
450+ * the new instructions generated from the successors of the old instruction.
451+ *
452+ * Furthermore, the entry block is augmented with `InitializeGroup` instructions.
453+ */
454+ cached
455+ Instruction getInstructionSuccessor ( Instruction instruction , EdgeKind kind ) {
456+ result = firstInstructionToInitializeGroup ( instruction , kind )
457+ or
458+ result = getNextInitializeGroupInstruction ( instruction , kind )
459+ or
460+ result = getInstructionSuccessorAfterInitializeGroup ( instruction , kind )
461+ or
462+ not isFirstInstructionBeforeInitializeGroup ( instruction , _) and
463+ result = getInstructionSuccessorAfterInitializeGroup0 ( instruction , kind )
464+ }
465+
386466 cached
387467 Instruction getInstructionBackEdgeSuccessor ( Instruction instruction , EdgeKind kind ) {
388468 exists ( OldInstruction oldInstruction |
@@ -699,7 +779,13 @@ private import DefUse
699779module DefUse {
700780 bindingset [ index, block]
701781 pragma [ inline_late]
702- private int getNonChiOffset ( int index , OldBlock block ) { result = 2 * index }
782+ private int getNonChiOffset ( int index , OldBlock block ) {
783+ exists ( IRFunction func | func = block .getEnclosingIRFunction ( ) |
784+ if getNewBlock ( block ) = func .getEntryBlock ( )
785+ then result = 2 * ( index + count ( VariableGroup vg | vg .getIRFunction ( ) = func ) )
786+ else result = 2 * index
787+ )
788+ }
703789
704790 bindingset [ index, block]
705791 pragma [ inline_late]
@@ -736,6 +822,26 @@ module DefUse {
736822 hasDefinition ( _, defLocation , defBlock , defOffset ) and
737823 result = getPhi ( defBlock , defLocation ) and
738824 actualDefLocation = defLocation
825+ or
826+ exists (
827+ Alias:: VariableGroup vg , int index , InitializeGroupInstruction initGroup ,
828+ Alias:: GroupedMemoryLocation gml
829+ |
830+ // Add 3 to account for the function prologue:
831+ // v1(void) = EnterFunction
832+ // m1(unknown) = AliasedDefinition
833+ // m2(unknown) = InitializeNonLocal
834+ index = 3 + vg .getInitializationOrder ( ) and
835+ not gml .isMayAccess ( ) and
836+ gml .isSome ( ) and
837+ gml .getGroup ( ) = vg and
838+ vg .getIRFunction ( ) .getEntryBlock ( ) = defBlock and
839+ initGroup = initializeGroup ( vg ) and
840+ ( defLocation = gml or defLocation = gml .getVirtualVariable ( ) ) and
841+ result = initGroup and
842+ defOffset = 2 * index and
843+ actualDefLocation = defLocation
844+ )
739845 }
740846
741847 /**
@@ -879,6 +985,16 @@ module DefUse {
879985 then offset = getChiOffset ( index , block ) // The use will be connected to the definition on the `Chi` instruction.
880986 else offset = getNonChiOffset ( index , block ) // The use will be connected to the definition on the original instruction.
881987 )
988+ or
989+ exists ( InitializeGroupInstruction initGroup , int index , VariableGroup vg |
990+ initGroup .getEnclosingIRFunction ( ) .getEntryBlock ( ) = getNewBlock ( block ) and
991+ vg = defLocation .( Alias:: GroupedMemoryLocation ) .getGroup ( ) and
992+ // EnterFunction + AliasedDefinition + InitializeNonLocal + index
993+ index = 3 + vg .getInitializationOrder ( ) and
994+ initGroup = initializeGroup ( vg ) and
995+ exists ( Alias:: getOverlap ( defLocation , useLocation ) ) and
996+ offset = 2 * index
997+ )
882998 }
883999
8841000 /**
0 commit comments