Skip to content

Commit dc22833

Browse files
committed
C++: Factor out IRBlock.qll differences
All three `IRBlock.qll` files are now identical again, and they are just a thin object-oriented layer on top of the three `IRBlockConstruction.qll` files, two of which are identical.
1 parent d88c9c6 commit dc22833

File tree

7 files changed

+190
-146
lines changed

7 files changed

+190
-146
lines changed

cpp/ql/src/semmle/code/cpp/ir/internal/IRBlock.qll

Lines changed: 8 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,27 @@
1+
private import IRInternal
2+
private import IRBlockConstruction
13
import Instruction
2-
import cpp
34
import semmle.code.cpp.ir.EdgeKind
45

5-
private predicate startsBasicBlock(Instruction instr) {
6-
not instr instanceof PhiInstruction and
7-
(
8-
count(Instruction predecessor |
9-
instr = predecessor.getASuccessor()
10-
) != 1 or // Multiple predecessors or no predecessor
11-
exists(Instruction predecessor |
12-
instr = predecessor.getASuccessor() and
13-
strictcount(Instruction other |
14-
other = predecessor.getASuccessor()
15-
) > 1
16-
) or // Predecessor has multiple successors
17-
exists(Instruction predecessor, EdgeKind kind |
18-
instr = predecessor.getSuccessor(kind) and
19-
not kind instanceof GotoEdge
20-
) // Incoming edge is not a GotoEdge
21-
)
22-
}
23-
24-
private predicate isEntryBlock(TIRBlock block) {
25-
block = MkIRBlock(any(EnterFunctionInstruction enter))
26-
}
27-
28-
private import Cached
29-
private cached module Cached {
30-
cached newtype TIRBlock =
31-
MkIRBlock(Instruction firstInstr) {
32-
startsBasicBlock(firstInstr)
33-
}
34-
35-
cached Instruction getInstruction(TIRBlock block, int index) {
36-
index = 0 and block = MkIRBlock(result) or
37-
(
38-
index > 0 and
39-
not startsBasicBlock(result) and
40-
exists(Instruction predecessor, GotoEdge edge |
41-
predecessor = getInstruction(block, index - 1) and
42-
result = predecessor.getSuccessor(edge)
43-
)
44-
)
45-
}
46-
47-
cached int getInstructionCount(TIRBlock block) {
48-
result = strictcount(getInstruction(block, _))
49-
}
50-
51-
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
52-
exists(Instruction predLast, Instruction succFirst |
53-
predLast = getInstruction(pred, getInstructionCount(pred) - 1) and
54-
succFirst = predLast.getSuccessor(kind) and
55-
succ = MkIRBlock(succFirst)
56-
)
57-
}
58-
59-
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
60-
blockSuccessor(pred, succ, _)
61-
}
62-
63-
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
64-
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
65-
}
66-
676
class IRBlock extends TIRBlock {
68-
Instruction firstInstr;
69-
70-
IRBlock() {
71-
this = MkIRBlock(firstInstr)
72-
}
73-
747
final string toString() {
75-
result = firstInstr.toString()
8+
result = getFirstInstruction(this).toString()
769
}
7710

7811
final Location getLocation() {
7912
result = getFirstInstruction().getLocation()
8013
}
8114

8215
final string getUniqueId() {
83-
result = firstInstr.getUniqueId()
16+
result = getFirstInstruction(this).getUniqueId()
8417
}
8518

8619
final Instruction getInstruction(int index) {
8720
result = getInstruction(this, index)
8821
}
8922

9023
final PhiInstruction getAPhiInstruction() {
91-
none()
24+
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
9225
}
9326

9427
final Instruction getAnInstruction() {
@@ -97,7 +30,7 @@ class IRBlock extends TIRBlock {
9730
}
9831

9932
final Instruction getFirstInstruction() {
100-
result = firstInstr
33+
result = getFirstInstruction(this)
10134
}
10235

10336
final Instruction getLastInstruction() {
@@ -109,11 +42,11 @@ class IRBlock extends TIRBlock {
10942
}
11043

11144
final FunctionIR getFunctionIR() {
112-
result = firstInstr.getFunctionIR()
45+
result = getFirstInstruction(this).getFunctionIR()
11346
}
11447

11548
final Function getFunction() {
116-
result = firstInstr.getFunction()
49+
result = getFirstInstruction(this).getFunction()
11750
}
11851

11952
final IRBlock getASuccessor() {
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
private import IRInternal
2+
import Instruction
3+
import cpp
4+
import semmle.code.cpp.ir.EdgeKind
5+
6+
private predicate startsBasicBlock(Instruction instr) {
7+
not instr instanceof PhiInstruction and
8+
(
9+
count(Instruction predecessor |
10+
instr = predecessor.getASuccessor()
11+
) != 1 or // Multiple predecessors or no predecessor
12+
exists(Instruction predecessor |
13+
instr = predecessor.getASuccessor() and
14+
strictcount(Instruction other |
15+
other = predecessor.getASuccessor()
16+
) > 1
17+
) or // Predecessor has multiple successors
18+
exists(Instruction predecessor, EdgeKind kind |
19+
instr = predecessor.getSuccessor(kind) and
20+
not kind instanceof GotoEdge
21+
) // Incoming edge is not a GotoEdge
22+
)
23+
}
24+
25+
private predicate isEntryBlock(TIRBlock block) {
26+
block = MkIRBlock(any(EnterFunctionInstruction enter))
27+
}
28+
29+
import Cached
30+
private cached module Cached {
31+
cached newtype TIRBlock =
32+
MkIRBlock(Instruction firstInstr) {
33+
startsBasicBlock(firstInstr)
34+
}
35+
36+
cached Instruction getInstruction(TIRBlock block, int index) {
37+
index = 0 and block = MkIRBlock(result) or
38+
(
39+
index > 0 and
40+
not startsBasicBlock(result) and
41+
exists(Instruction predecessor, GotoEdge edge |
42+
predecessor = getInstruction(block, index - 1) and
43+
result = predecessor.getSuccessor(edge)
44+
)
45+
)
46+
}
47+
48+
cached int getInstructionCount(TIRBlock block) {
49+
result = strictcount(getInstruction(block, _))
50+
}
51+
52+
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
53+
exists(Instruction predLast, Instruction succFirst |
54+
predLast = getInstruction(pred, getInstructionCount(pred) - 1) and
55+
succFirst = predLast.getSuccessor(kind) and
56+
succ = MkIRBlock(succFirst)
57+
)
58+
}
59+
60+
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
61+
blockSuccessor(pred, succ, _)
62+
}
63+
64+
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
65+
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
66+
}
67+
68+
Instruction getFirstInstruction(TIRBlock block) {
69+
block = MkIRBlock(result)
70+
}

cpp/ql/src/semmle/code/cpp/ir/internal/IRConstruction.qll

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import cpp
22
import semmle.code.cpp.ir.IR
33
private import InstructionTag
4-
private import Opcode
54
private import TempVariableTag
65
private import TranslatedElement
76
private import TranslatedFunction
Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,27 @@
11
private import IRInternal
2-
private import Construction::OldIR as OldIR
2+
private import IRBlockConstruction
33
import Instruction
44
import semmle.code.cpp.ir.EdgeKind
55

6-
cached newtype TIRBlock = MkIRBlock(OldIR::IRBlock oldBlock)
7-
86
class IRBlock extends TIRBlock {
9-
OldIR::IRBlock oldBlock;
10-
11-
IRBlock() {
12-
this = MkIRBlock(oldBlock)
13-
}
14-
157
final string toString() {
16-
result = oldBlock.toString()
8+
result = getFirstInstruction(this).toString()
179
}
1810

1911
final Location getLocation() {
20-
result = oldBlock.getLocation()
12+
result = getFirstInstruction().getLocation()
2113
}
22-
14+
2315
final string getUniqueId() {
24-
result = oldBlock.getUniqueId()
16+
result = getFirstInstruction(this).getUniqueId()
2517
}
26-
18+
2719
final Instruction getInstruction(int index) {
28-
Construction::getOldInstruction(result) = oldBlock.getInstruction(index)
20+
result = getInstruction(this, index)
2921
}
3022

3123
final PhiInstruction getAPhiInstruction() {
32-
Construction::getPhiInstructionBlockStart(result) =
33-
getFirstInstruction()
24+
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
3425
}
3526

3627
final Instruction getAnInstruction() {
@@ -39,47 +30,43 @@ class IRBlock extends TIRBlock {
3930
}
4031

4132
final Instruction getFirstInstruction() {
42-
Construction::getOldInstruction(result) = oldBlock.getFirstInstruction()
33+
result = getFirstInstruction(this)
4334
}
4435

4536
final Instruction getLastInstruction() {
46-
Construction::getOldInstruction(result) = oldBlock.getLastInstruction()
37+
result = getInstruction(getInstructionCount() - 1)
4738
}
4839

4940
final int getInstructionCount() {
50-
result = oldBlock.getInstructionCount()
41+
result = strictcount(getInstruction(_))
5142
}
5243

5344
final FunctionIR getFunctionIR() {
54-
result = getFirstInstruction().getFunctionIR()
45+
result = getFirstInstruction(this).getFunctionIR()
5546
}
5647

5748
final Function getFunction() {
58-
result = getFirstInstruction().getFunction()
49+
result = getFirstInstruction(this).getFunction()
5950
}
6051

6152
final IRBlock getASuccessor() {
62-
result = MkIRBlock(oldBlock.getASuccessor())
53+
blockSuccessor(this, result)
6354
}
6455

6556
final IRBlock getAPredecessor() {
66-
result.getASuccessor() = this
57+
blockSuccessor(result, this)
6758
}
6859

6960
final IRBlock getSuccessor(EdgeKind kind) {
70-
result = MkIRBlock(oldBlock.getSuccessor(kind))
61+
blockSuccessor(this, result, kind)
7162
}
7263

7364
final predicate immediatelyDominates(IRBlock block) {
74-
oldBlock.immediatelyDominates(block.getOldBlock())
65+
blockImmediatelyDominates(this, block)
7566
}
7667

7768
final predicate strictlyDominates(IRBlock block) {
78-
// This is recomputed from scratch rather than reusing the corresponding
79-
// predicate of `getOldBlock` because `getOldBlock.strictlyDominates/1` may
80-
// at run time be a compactly stored transitive closure that we don't want
81-
// to risk materializing in order to join with `MkIRBlock`.
82-
immediatelyDominates+(block)
69+
blockImmediatelyDominates+(this, block)
8370
}
8471

8572
final predicate dominates(IRBlock block) {
@@ -91,8 +78,4 @@ class IRBlock extends TIRBlock {
9178
dominates(result.getAPredecessor()) and
9279
not strictlyDominates(result)
9380
}
94-
95-
private OldIR::IRBlock getOldBlock() {
96-
result = oldBlock
97-
}
9881
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
private import IRInternal
2+
private import Construction::OldIR as OldIR
3+
import Instruction
4+
5+
import Cached
6+
private cached module Cached {
7+
cached newtype TIRBlock = MkIRBlock(OldIR::IRBlock oldBlock)
8+
9+
private OldIR::IRBlock getOldBlock(TIRBlock block) {
10+
block = MkIRBlock(result)
11+
}
12+
13+
cached Instruction getInstruction(TIRBlock block, int index) {
14+
Construction::getOldInstruction(result) =
15+
getOldBlock(block).getInstruction(index)
16+
}
17+
18+
cached int getInstructionCount(TIRBlock block) {
19+
result = getOldBlock(block).getInstructionCount()
20+
}
21+
22+
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
23+
succ = MkIRBlock(getOldBlock(pred).getSuccessor(kind))
24+
}
25+
26+
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
27+
blockSuccessor(pred, succ, _)
28+
}
29+
30+
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) {
31+
getOldBlock(dominator).immediatelyDominates(getOldBlock(block))
32+
}
33+
34+
cached Instruction getFirstInstruction(TIRBlock block) {
35+
Construction::getOldInstruction(result) =
36+
getOldBlock(block).getFirstInstruction()
37+
}
38+
}

0 commit comments

Comments
 (0)