Skip to content

Commit db525f5

Browse files
committed
C++: Sync identical files.
1 parent 03ec184 commit db525f5

File tree

1 file changed

+171
-21
lines changed

1 file changed

+171
-21
lines changed

cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll

Lines changed: 171 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,43 @@ private class OldInstruction = Reachability::ReachableInstruction;
1515

1616
import 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+
1855
cached
1956
private module Cached {
2057
cached
@@ -45,7 +82,8 @@ private module Cached {
4582
}
4683

4784
class TStageInstruction =
48-
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction;
85+
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction or
86+
TInitializeGroupInstruction;
4987

5088
/**
5189
* If `oldInstruction` is a `Phi` instruction that has exactly one reachable predecessor block,
@@ -78,6 +116,8 @@ private module Cached {
78116
or
79117
instr instanceof TChiInstruction
80118
or
119+
instr instanceof TInitializeGroupInstruction
120+
or
81121
instr instanceof TUnreachedInstruction
82122
}
83123

@@ -123,7 +163,8 @@ private module Cached {
123163
predicate hasModeledMemoryResult(Instruction instruction) {
124164
canModelResultForOldInstruction(getOldInstruction(instruction)) or
125165
instruction instanceof PhiInstruction or // Phis always have modeled results
126-
instruction instanceof ChiInstruction // Chis always have modeled results
166+
instruction instanceof ChiInstruction or // Chis always have modeled results
167+
instruction instanceof InitializeGroupInstruction // Group initializers always have modeled results
127168
}
128169

129170
cached
@@ -143,7 +184,7 @@ private module Cached {
143184
// conflated if it's associated with a conflated location.
144185
exists(Alias::MemoryLocation location |
145186
instruction = getPhi(_, location) and
146-
not exists(location.getAllocation())
187+
not exists(location.getAnAllocation())
147188
)
148189
}
149190

@@ -264,7 +305,12 @@ private module Cached {
264305
}
265306

266307
cached
267-
IRVariable getAnInitializeGroupVariable(InitializeGroupInstruction instr) { none() }
308+
IRVariable getAnInitializeGroupVariable(InitializeGroupInstruction init) {
309+
exists(Alias::VariableGroup vg |
310+
init = initializeGroup(vg) and
311+
result = vg.getAnAllocation().getABaseInstruction().(VariableInstruction).getIRVariable()
312+
)
313+
}
268314

269315
/**
270316
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
@@ -347,14 +393,28 @@ private module Cached {
347393
)
348394
}
349395

350-
/*
351-
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
352-
* that node is its successor in the new successor relation, and the Chi node's successors are
353-
* the new instructions generated from the successors of the old instruction
354-
*/
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+
}
355405

356-
cached
357-
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+
) {
358418
if hasChiNode(_, getOldInstruction(instruction))
359419
then
360420
result = getChi(getOldInstruction(instruction)) and
@@ -374,6 +434,35 @@ private module Cached {
374434
)
375435
}
376436

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+
377466
cached
378467
Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
379468
exists(OldInstruction oldInstruction |
@@ -409,6 +498,11 @@ private module Cached {
409498
exists(IRFunctionBase irFunc |
410499
instr = unreachedInstruction(irFunc) and result = irFunc.getFunction()
411500
)
501+
or
502+
exists(Alias::VariableGroup vg |
503+
instr = initializeGroup(vg) and
504+
result = vg.getIRFunction().getFunction()
505+
)
412506
}
413507

414508
cached
@@ -426,6 +520,11 @@ private module Cached {
426520
result = vvar.getType()
427521
)
428522
or
523+
exists(Alias::VariableGroup vg |
524+
instr = initializeGroup(vg) and
525+
result = vg.getType()
526+
)
527+
or
429528
instr = reusedPhiInstruction(_) and
430529
result = instr.(OldInstruction).getResultLanguageType()
431530
or
@@ -451,6 +550,8 @@ private module Cached {
451550
or
452551
instr = chiInstruction(_) and opcode instanceof Opcode::Chi
453552
or
553+
instr = initializeGroup(_) and opcode instanceof Opcode::InitializeGroup
554+
or
454555
instr = unreachedInstruction(_) and opcode instanceof Opcode::Unreached
455556
}
456557

@@ -467,6 +568,11 @@ private module Cached {
467568
instr = chiInstruction(primaryInstr) and result = primaryInstr.getEnclosingIRFunction()
468569
)
469570
or
571+
exists(Alias::VariableGroup vg |
572+
instr = initializeGroup(vg) and
573+
result = vg.getIRFunction()
574+
)
575+
or
470576
instr = unreachedInstruction(result)
471577
}
472578

@@ -671,19 +777,30 @@ private import DefUse
671777
* potentially very sparse.
672778
*/
673779
module DefUse {
780+
bindingset[index, block]
781+
pragma[inline_late]
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+
}
789+
790+
bindingset[index, block]
791+
pragma[inline_late]
792+
private int getChiOffset(int index, OldBlock block) { result = getNonChiOffset(index, block) + 1 }
793+
674794
/**
675795
* Gets the `Instruction` for the definition at offset `defOffset` in block `defBlock`.
676796
*/
677797
Instruction getDefinitionOrChiInstruction(
678798
OldBlock defBlock, int defOffset, Alias::MemoryLocation defLocation,
679799
Alias::MemoryLocation actualDefLocation
680800
) {
681-
exists(OldInstruction oldInstr, int oldOffset |
682-
oldInstr = defBlock.getInstruction(oldOffset) and
683-
oldOffset >= 0
684-
|
801+
exists(OldInstruction oldInstr, int oldOffset | oldInstr = defBlock.getInstruction(oldOffset) |
685802
// An odd offset corresponds to the `Chi` instruction.
686-
defOffset = oldOffset * 2 + 1 and
803+
defOffset = getChiOffset(oldOffset, defBlock) and
687804
result = getChi(oldInstr) and
688805
(
689806
defLocation = Alias::getResultMemoryLocation(oldInstr) or
@@ -692,7 +809,7 @@ module DefUse {
692809
actualDefLocation = defLocation.getVirtualVariable()
693810
or
694811
// An even offset corresponds to the original instruction.
695-
defOffset = oldOffset * 2 and
812+
defOffset = getNonChiOffset(oldOffset, defBlock) and
696813
result = getNewInstruction(oldInstr) and
697814
(
698815
defLocation = Alias::getResultMemoryLocation(oldInstr) or
@@ -705,6 +822,26 @@ module DefUse {
705822
hasDefinition(_, defLocation, defBlock, defOffset) and
706823
result = getPhi(defBlock, defLocation) and
707824
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+
)
708845
}
709846

710847
/**
@@ -845,8 +982,18 @@ module DefUse {
845982
block.getInstruction(index) = def and
846983
overlap = Alias::getOverlap(defLocation, useLocation) and
847984
if overlap instanceof MayPartiallyOverlap
848-
then offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction.
849-
else offset = index * 2 // The use will be connected to the definition on the original instruction.
985+
then offset = getChiOffset(index, block) // The use will be connected to the definition on the `Chi` instruction.
986+
else offset = getNonChiOffset(index, block) // The use will be connected to the definition on the original instruction.
987+
)
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
850997
)
851998
}
852999

@@ -907,10 +1054,11 @@ module DefUse {
9071054
block.getInstruction(index) = use and
9081055
(
9091056
// A direct use of the location.
910-
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and offset = index * 2
1057+
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and
1058+
offset = getNonChiOffset(index, block)
9111059
or
9121060
// A `Chi` instruction will include a use of the virtual variable.
913-
hasChiNode(useLocation, use) and offset = (index * 2) + 1
1061+
hasChiNode(useLocation, use) and offset = getChiOffset(index, block)
9141062
)
9151063
)
9161064
}
@@ -1061,4 +1209,6 @@ module Ssa {
10611209
predicate hasChiInstruction = Cached::hasChiInstructionCached/1;
10621210

10631211
predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1;
1212+
1213+
class VariableGroup = Alias::VariableGroup;
10641214
}

0 commit comments

Comments
 (0)