Skip to content

Commit 3735cb6

Browse files
committed
C++: No InstructionTag in SSAConstruction
This does to `SSAConstruction` what the previous commit did to `IRConstruction`. An instruction in `SSAConstruction` is now defined in terms of how it was created rather than what it can be queried for. Effectively, this defines `TInstruction` as `TInstructionTag` was defined before and then removes `TInstructionTag` from `SSAConstruction`. This also has the benefit of removing the concept of an instruction tag from the public predicates on `Instruction`.
1 parent 8ae3551 commit 3735cb6

File tree

7 files changed

+236
-266
lines changed

7 files changed

+236
-266
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import semmle.code.cpp.ir.implementation.Opcode
1010
private import semmle.code.cpp.ir.implementation.Opcode
1111
private import semmle.code.cpp.ir.internal.OperandTag
1212

13-
class InstructionTag = Construction::InstructionTagType;
14-
1513
module InstructionSanity {
1614
/**
1715
* Holds if the instruction `instr` should be expected to have an operand
@@ -463,10 +461,6 @@ class Instruction extends Construction::TInstruction {
463461
result = Construction::getInstructionOpcode(this)
464462
}
465463

466-
final InstructionTag getTag() {
467-
result = Construction::getInstructionTag(this)
468-
}
469-
470464
/**
471465
* Gets all direct uses of the result of this instruction.
472466
*/

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll

Lines changed: 109 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -7,60 +7,21 @@ private import NewIR
77
private class OldBlock = Reachability::ReachableBlock;
88
private class OldInstruction = Reachability::ReachableInstruction;
99

10-
InstructionTag getInstructionTag(Instruction instruction) {
11-
instruction = MkInstruction(_, _, _, result, _, _)
12-
}
13-
14-
Locatable getInstructionAST(Instruction instruction) {
15-
instruction = MkInstruction(_, _, result, _, _, _)
16-
}
17-
18-
predicate instructionHasType(Instruction instruction, Type type, boolean isGLValue) {
19-
instruction = MkInstruction(_, _, _, _, type, isGLValue)
20-
}
21-
22-
Opcode getInstructionOpcode(Instruction instruction) {
23-
instruction = MkInstruction(_, result, _, _, _, _)
24-
}
25-
26-
FunctionIR getInstructionEnclosingFunctionIR(Instruction instruction) {
27-
instruction = MkInstruction(result, _, _, _, _, _)
28-
}
29-
3010
import Cached
3111
cached private module Cached {
3212

3313
private IRBlock getNewBlock(OldBlock oldBlock) {
3414
result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction())
3515
}
3616

37-
cached newtype TInstructionTag =
38-
WrappedInstructionTag(OldInstruction oldInstruction) {
39-
not oldInstruction instanceof OldIR::PhiInstruction
40-
} or
41-
PhiTag(Alias::VirtualVariable vvar, OldBlock block) {
42-
hasPhiNode(vvar, block)
43-
} or
44-
ChiTag(OldInstruction oldInstruction) {
45-
not oldInstruction instanceof OldIR::PhiInstruction and
46-
hasChiNode(_, oldInstruction)
47-
} or
48-
UnreachedTag()
49-
50-
cached class InstructionTagType extends TInstructionTag {
51-
cached final string toString() {
52-
result = "Tag"
53-
}
54-
}
55-
5617
cached predicate functionHasIR(Function func) {
5718
exists(OldIR::FunctionIR funcIR |
5819
funcIR.getFunction() = func
5920
)
6021
}
6122

6223
cached OldInstruction getOldInstruction(Instruction instr) {
63-
instr.getTag() = WrappedInstructionTag(result)
24+
instr = WrappedInstruction(result)
6425
}
6526

6627
private Instruction getNewInstruction(OldInstruction instr) {
@@ -72,24 +33,12 @@ cached private module Cached {
7233
* corresponding to `instr` if there is no `Chi` node.
7334
*/
7435
private Instruction getNewFinalInstruction(OldInstruction instr) {
75-
result = getChiInstruction(instr)
36+
result = Chi(instr)
7637
or
77-
not exists(getChiInstruction(instr)) and
38+
not exists(Chi(instr)) and
7839
result = getNewInstruction(instr)
7940
}
8041

81-
private PhiInstruction getPhiInstruction(Function func, OldBlock oldBlock,
82-
Alias::VirtualVariable vvar) {
83-
result.getFunction() = func and
84-
result.getAST() = oldBlock.getFirstInstruction().getAST() and
85-
result.getTag() = PhiTag(vvar, oldBlock)
86-
}
87-
88-
private ChiInstruction getChiInstruction (OldInstruction instr) {
89-
hasChiNode(_, instr) and
90-
result.getTag() = ChiTag(instr)
91-
}
92-
9342
private IRVariable getNewIRVariable(OldIR::IRVariable var) {
9443
result.getFunction() = var.getFunction() and
9544
(
@@ -108,54 +57,23 @@ cached private module Cached {
10857
}
10958

11059
cached newtype TInstruction =
111-
MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast,
112-
InstructionTag tag, Type resultType, boolean isGLValue) {
113-
hasInstruction(funcIR.getFunction(), opcode, ast, tag,
114-
resultType, isGLValue)
60+
WrappedInstruction(OldInstruction oldInstruction) {
61+
not oldInstruction instanceof OldIR::PhiInstruction
62+
} or
63+
Phi(OldBlock block, Alias::VirtualVariable vvar) {
64+
hasPhiNode(vvar, block)
65+
} or
66+
Chi(OldInstruction oldInstruction) {
67+
not oldInstruction instanceof OldIR::PhiInstruction and
68+
hasChiNode(_, oldInstruction)
69+
} or
70+
Unreached(Function function) {
71+
exists(OldInstruction oldInstruction |
72+
function = oldInstruction.getFunction() and
73+
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
74+
)
11575
}
11676

117-
private predicate hasInstruction(Function func, Opcode opcode, Locatable ast,
118-
InstructionTag tag, Type resultType, boolean isGLValue) {
119-
exists(OldInstruction instr |
120-
instr.getFunction() = func and
121-
instr.getOpcode() = opcode and
122-
instr.getAST() = ast and
123-
WrappedInstructionTag(instr) = tag and
124-
instr.getResultType() = resultType and
125-
if instr.isGLValue() then
126-
isGLValue = true
127-
else
128-
isGLValue = false
129-
) or
130-
exists(OldBlock block, Alias::VirtualVariable vvar |
131-
hasPhiNode(vvar, block) and
132-
block.getFunction() = func and
133-
opcode instanceof Opcode::Phi and
134-
ast = block.getFirstInstruction().getAST() and
135-
tag = PhiTag(vvar, block) and
136-
resultType = vvar.getType() and
137-
isGLValue = false
138-
) or
139-
exists(OldInstruction instr, Alias::VirtualVariable vvar |
140-
hasChiNode(vvar, instr) and
141-
instr.getFunction() = func and
142-
opcode instanceof Opcode::Chi and
143-
ast = instr.getAST() and
144-
tag = ChiTag(instr) and
145-
resultType = vvar.getType() and
146-
isGLValue = false
147-
) or
148-
exists(OldInstruction oldInstruction |
149-
func = oldInstruction.getFunction() and
150-
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _) and
151-
tag = UnreachedTag() and
152-
opcode instanceof Opcode::Unreached and
153-
ast = func and
154-
resultType instanceof VoidType and
155-
isGLValue = false
156-
)
157-
}
158-
15977
cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag,
16078
Type type) {
16179
exists(OldIR::IRTempVariable var |
@@ -189,7 +107,7 @@ cached private module Cached {
189107
if defIndex >= 0 then
190108
result = getNewFinalInstruction(defBlock.getInstruction(defIndex))
191109
else
192-
result = getPhiInstruction(instruction.getFunction(), defBlock, vvar)
110+
result = Phi(defBlock, vvar)
193111
)
194112
)
195113
else (
@@ -209,7 +127,7 @@ cached private module Cached {
209127
else
210128
result = getNewInstruction(oldOperand.getDefinitionInstruction())
211129
) or
212-
instruction.getTag() = ChiTag(getOldInstruction(result)) and
130+
instruction = Chi(getOldInstruction(result)) and
213131
tag instanceof ChiPartialOperandTag
214132
or
215133
exists(FunctionIR f |
@@ -228,35 +146,35 @@ cached private module Cached {
228146
OldBlock defBlock, int defRank, int defIndex, OldBlock predBlock |
229147
hasPhiNode(vvar, phiBlock) and
230148
predBlock = phiBlock.getAFeasiblePredecessor() and
231-
instr.getTag() = PhiTag(vvar, phiBlock) and
149+
instr = Phi(phiBlock, vvar) and
232150
newPredecessorBlock = getNewBlock(predBlock) and
233151
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
234152
definitionReachesEndOfBlock(vvar, defBlock, defRank, predBlock) and
235153
if defIndex >= 0 then
236154
result = getNewFinalInstruction(defBlock.getInstruction(defIndex))
237155
else
238-
result = getPhiInstruction(instr.getFunction(), defBlock, vvar)
156+
result = Phi(defBlock, vvar)
239157
)
240158
}
241159

242160
cached Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
243161
exists(Alias::VirtualVariable vvar, OldInstruction oldInstr, OldBlock defBlock,
244162
int defRank, int defIndex, OldBlock useBlock, int useRank |
245-
ChiTag(oldInstr) = chiInstr.getTag() and
163+
chiInstr = Chi(oldInstr) and
246164
vvar = Alias::getResultMemoryAccess(oldInstr).getVirtualVariable() and
247165
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
248166
hasUseAtRank(vvar, useBlock, useRank, oldInstr) and
249167
definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and
250168
if defIndex >= 0 then
251169
result = getNewFinalInstruction(defBlock.getInstruction(defIndex))
252170
else
253-
result = getPhiInstruction(chiInstr.getFunction(), defBlock, vvar)
171+
result = Phi(defBlock, vvar)
254172
)
255173
}
256174

257175
cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) {
258176
exists(OldBlock oldBlock |
259-
instr.getTag() = PhiTag(_, oldBlock) and
177+
instr = Phi(oldBlock, _) and
260178
result = getNewInstruction(oldBlock.getFirstInstruction())
261179
)
262180
}
@@ -277,23 +195,22 @@ cached private module Cached {
277195
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
278196
if(hasChiNode(_, getOldInstruction(instruction)))
279197
then
280-
result = getChiInstruction(getOldInstruction(instruction)) and
198+
result = Chi(getOldInstruction(instruction)) and
281199
kind instanceof GotoEdge
282200
else (
283201
exists(OldInstruction oldInstruction |
284202
oldInstruction = getOldInstruction(instruction) and
285203
(
286204
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) then (
287-
result.getTag() = UnreachedTag() and
288-
result.getFunction() = instruction.getFunction()
205+
result = Unreached(instruction.getFunction())
289206
)
290207
else (
291208
result = getNewInstruction(oldInstruction.getSuccessor(kind))
292209
)
293210
)
294211
) or
295212
exists(OldInstruction oldInstruction |
296-
instruction = getChiInstruction(oldInstruction) and
213+
instruction = Chi(oldInstruction) and
297214
result = getNewInstruction(oldInstruction.getSuccessor(kind))
298215
)
299216
)
@@ -311,11 +228,88 @@ cached private module Cached {
311228
// `oldInstruction`, in which case the back edge should come out of the
312229
// chi node instead.
313230
if hasChiNode(_, oldInstruction)
314-
then instruction = getChiInstruction(oldInstruction)
231+
then instruction = Chi(oldInstruction)
315232
else instruction = getNewInstruction(oldInstruction)
316233
)
317234
}
318235

236+
cached Locatable getInstructionAST(Instruction instruction) {
237+
exists(OldInstruction oldInstruction |
238+
instruction = WrappedInstruction(oldInstruction)
239+
or
240+
instruction = Chi(oldInstruction)
241+
|
242+
result = oldInstruction.getAST()
243+
)
244+
or
245+
exists(OldBlock block |
246+
instruction = Phi(block, _) and
247+
result = block.getFirstInstruction().getAST()
248+
)
249+
or
250+
instruction = Unreached(result)
251+
}
252+
253+
cached predicate instructionHasType(Instruction instruction, Type type, boolean isGLValue) {
254+
exists(OldInstruction oldInstruction |
255+
instruction = WrappedInstruction(oldInstruction) and
256+
type = oldInstruction.getResultType() and
257+
if oldInstruction.isGLValue()
258+
then isGLValue = true
259+
else isGLValue = false
260+
)
261+
or
262+
exists(OldInstruction oldInstruction, Alias::VirtualVariable vvar |
263+
instruction = Chi(oldInstruction) and
264+
hasChiNode(vvar, oldInstruction) and
265+
type = vvar.getType() and
266+
isGLValue = false
267+
)
268+
or
269+
exists(Alias::VirtualVariable vvar |
270+
instruction = Phi(_, vvar) and
271+
type = vvar.getType() and
272+
isGLValue = false
273+
)
274+
or
275+
instruction = Unreached(_) and
276+
type instanceof VoidType and
277+
isGLValue = false
278+
}
279+
280+
cached Opcode getInstructionOpcode(Instruction instruction) {
281+
exists(OldInstruction oldInstruction |
282+
instruction = WrappedInstruction(oldInstruction) and
283+
result = oldInstruction.getOpcode()
284+
)
285+
or
286+
instruction instanceof Chi and
287+
result instanceof Opcode::Chi
288+
or
289+
instruction instanceof Phi and
290+
result instanceof Opcode::Phi
291+
or
292+
instruction instanceof Unreached and
293+
result instanceof Opcode::Unreached
294+
}
295+
296+
cached FunctionIR getInstructionEnclosingFunctionIR(Instruction instruction) {
297+
exists(OldInstruction oldInstruction |
298+
instruction = WrappedInstruction(oldInstruction)
299+
or
300+
instruction = Chi(oldInstruction)
301+
|
302+
result.getFunction() = oldInstruction.getFunction()
303+
)
304+
or
305+
exists(OldBlock block |
306+
instruction = Phi(block, _) and
307+
result.getFunction() = block.getFunction()
308+
)
309+
or
310+
instruction = Unreached(result.getFunction())
311+
}
312+
319313
cached IRVariable getInstructionVariable(Instruction instruction) {
320314
result = getNewIRVariable(getOldInstruction(instruction).(OldIR::VariableInstruction).getVariable())
321315
}
@@ -366,7 +360,7 @@ cached private module Cached {
366360
)
367361
or
368362
exists(OldIR::Instruction oldInstruction |
369-
instruction.getTag() = ChiTag(oldInstruction) and
363+
instruction = Chi(oldInstruction) and
370364
result = getNewInstruction(oldInstruction)
371365
)
372366
}
@@ -555,11 +549,11 @@ cached private module CachedForDebugging {
555549
result = "NonSSA: " + oldInstr.getUniqueId()
556550
) or
557551
exists(Alias::VirtualVariable vvar, OldBlock phiBlock |
558-
instr.getTag() = PhiTag(vvar, phiBlock) and
552+
instr = Phi(phiBlock, vvar) and
559553
result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId()
560554
) or
561555
(
562-
instr.getTag() = UnreachedTag() and
556+
instr = Unreached(_) and
563557
result = "Unreached"
564558
)
565559
}

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import semmle.code.cpp.ir.implementation.Opcode
1010
private import semmle.code.cpp.ir.implementation.Opcode
1111
private import semmle.code.cpp.ir.internal.OperandTag
1212

13-
class InstructionTag = Construction::InstructionTagType;
14-
1513
module InstructionSanity {
1614
/**
1715
* Holds if the instruction `instr` should be expected to have an operand
@@ -463,10 +461,6 @@ class Instruction extends Construction::TInstruction {
463461
result = Construction::getInstructionOpcode(this)
464462
}
465463

466-
final InstructionTag getTag() {
467-
result = Construction::getInstructionTag(this)
468-
}
469-
470464
/**
471465
* Gets all direct uses of the result of this instruction.
472466
*/

0 commit comments

Comments
 (0)