Skip to content

Commit dc20924

Browse files
Merge pull request #866 from jbj/ir-TInstruction-normalize
C++: Normalize TInstruction
2 parents f47a77b + 3735cb6 commit dc20924

File tree

8 files changed

+532
-557
lines changed

8 files changed

+532
-557
lines changed

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

Lines changed: 90 additions & 107 deletions
Large diffs are not rendered by default.

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

Lines changed: 109 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,14 @@ cached private module Cached {
1414
result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction())
1515
}
1616

17-
cached newtype TInstructionTag =
18-
WrappedInstructionTag(OldInstruction oldInstruction) {
19-
not oldInstruction instanceof OldIR::PhiInstruction
20-
} or
21-
PhiTag(Alias::VirtualVariable vvar, OldBlock block) {
22-
hasPhiNode(vvar, block)
23-
} or
24-
ChiTag(OldInstruction oldInstruction) {
25-
not oldInstruction instanceof OldIR::PhiInstruction and
26-
hasChiNode(_, oldInstruction)
27-
} or
28-
UnreachedTag()
29-
30-
cached class InstructionTagType extends TInstructionTag {
31-
cached final string toString() {
32-
result = "Tag"
33-
}
34-
}
35-
3617
cached predicate functionHasIR(Function func) {
3718
exists(OldIR::FunctionIR funcIR |
3819
funcIR.getFunction() = func
3920
)
4021
}
4122

4223
cached OldInstruction getOldInstruction(Instruction instr) {
43-
instr.getTag() = WrappedInstructionTag(result)
24+
instr = WrappedInstruction(result)
4425
}
4526

4627
private Instruction getNewInstruction(OldInstruction instr) {
@@ -52,24 +33,12 @@ cached private module Cached {
5233
* corresponding to `instr` if there is no `Chi` node.
5334
*/
5435
private Instruction getNewFinalInstruction(OldInstruction instr) {
55-
result = getChiInstruction(instr)
36+
result = Chi(instr)
5637
or
57-
not exists(getChiInstruction(instr)) and
38+
not exists(Chi(instr)) and
5839
result = getNewInstruction(instr)
5940
}
6041

61-
private PhiInstruction getPhiInstruction(Function func, OldBlock oldBlock,
62-
Alias::VirtualVariable vvar) {
63-
result.getFunction() = func and
64-
result.getAST() = oldBlock.getFirstInstruction().getAST() and
65-
result.getTag() = PhiTag(vvar, oldBlock)
66-
}
67-
68-
private ChiInstruction getChiInstruction (OldInstruction instr) {
69-
hasChiNode(_, instr) and
70-
result.getTag() = ChiTag(instr)
71-
}
72-
7342
private IRVariable getNewIRVariable(OldIR::IRVariable var) {
7443
result.getFunction() = var.getFunction() and
7544
(
@@ -88,54 +57,23 @@ cached private module Cached {
8857
}
8958

9059
cached newtype TInstruction =
91-
MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast,
92-
InstructionTag tag, Type resultType, boolean isGLValue) {
93-
hasInstruction(funcIR.getFunction(), opcode, ast, tag,
94-
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+
)
9575
}
9676

97-
private predicate hasInstruction(Function func, Opcode opcode, Locatable ast,
98-
InstructionTag tag, Type resultType, boolean isGLValue) {
99-
exists(OldInstruction instr |
100-
instr.getFunction() = func and
101-
instr.getOpcode() = opcode and
102-
instr.getAST() = ast and
103-
WrappedInstructionTag(instr) = tag and
104-
instr.getResultType() = resultType and
105-
if instr.isGLValue() then
106-
isGLValue = true
107-
else
108-
isGLValue = false
109-
) or
110-
exists(OldBlock block, Alias::VirtualVariable vvar |
111-
hasPhiNode(vvar, block) and
112-
block.getFunction() = func and
113-
opcode instanceof Opcode::Phi and
114-
ast = block.getFirstInstruction().getAST() and
115-
tag = PhiTag(vvar, block) and
116-
resultType = vvar.getType() and
117-
isGLValue = false
118-
) or
119-
exists(OldInstruction instr, Alias::VirtualVariable vvar |
120-
hasChiNode(vvar, instr) and
121-
instr.getFunction() = func and
122-
opcode instanceof Opcode::Chi and
123-
ast = instr.getAST() and
124-
tag = ChiTag(instr) and
125-
resultType = vvar.getType() and
126-
isGLValue = false
127-
) or
128-
exists(OldInstruction oldInstruction |
129-
func = oldInstruction.getFunction() and
130-
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _) and
131-
tag = UnreachedTag() and
132-
opcode instanceof Opcode::Unreached and
133-
ast = func and
134-
resultType instanceof VoidType and
135-
isGLValue = false
136-
)
137-
}
138-
13977
cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag,
14078
Type type) {
14179
exists(OldIR::IRTempVariable var |
@@ -169,7 +107,7 @@ cached private module Cached {
169107
if defIndex >= 0 then
170108
result = getNewFinalInstruction(defBlock.getInstruction(defIndex))
171109
else
172-
result = getPhiInstruction(instruction.getFunction(), defBlock, vvar)
110+
result = Phi(defBlock, vvar)
173111
)
174112
)
175113
else (
@@ -189,7 +127,7 @@ cached private module Cached {
189127
else
190128
result = getNewInstruction(oldOperand.getDefinitionInstruction())
191129
) or
192-
instruction.getTag() = ChiTag(getOldInstruction(result)) and
130+
instruction = Chi(getOldInstruction(result)) and
193131
tag instanceof ChiPartialOperandTag
194132
or
195133
exists(FunctionIR f |
@@ -208,35 +146,35 @@ cached private module Cached {
208146
OldBlock defBlock, int defRank, int defIndex, OldBlock predBlock |
209147
hasPhiNode(vvar, phiBlock) and
210148
predBlock = phiBlock.getAFeasiblePredecessor() and
211-
instr.getTag() = PhiTag(vvar, phiBlock) and
149+
instr = Phi(phiBlock, vvar) and
212150
newPredecessorBlock = getNewBlock(predBlock) and
213151
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
214152
definitionReachesEndOfBlock(vvar, defBlock, defRank, predBlock) and
215153
if defIndex >= 0 then
216154
result = getNewFinalInstruction(defBlock.getInstruction(defIndex))
217155
else
218-
result = getPhiInstruction(instr.getFunction(), defBlock, vvar)
156+
result = Phi(defBlock, vvar)
219157
)
220158
}
221159

222160
cached Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
223161
exists(Alias::VirtualVariable vvar, OldInstruction oldInstr, OldBlock defBlock,
224162
int defRank, int defIndex, OldBlock useBlock, int useRank |
225-
ChiTag(oldInstr) = chiInstr.getTag() and
163+
chiInstr = Chi(oldInstr) and
226164
vvar = Alias::getResultMemoryAccess(oldInstr).getVirtualVariable() and
227165
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
228166
hasUseAtRank(vvar, useBlock, useRank, oldInstr) and
229167
definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and
230168
if defIndex >= 0 then
231169
result = getNewFinalInstruction(defBlock.getInstruction(defIndex))
232170
else
233-
result = getPhiInstruction(chiInstr.getFunction(), defBlock, vvar)
171+
result = Phi(defBlock, vvar)
234172
)
235173
}
236174

237175
cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) {
238176
exists(OldBlock oldBlock |
239-
instr.getTag() = PhiTag(_, oldBlock) and
177+
instr = Phi(oldBlock, _) and
240178
result = getNewInstruction(oldBlock.getFirstInstruction())
241179
)
242180
}
@@ -257,23 +195,22 @@ cached private module Cached {
257195
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
258196
if(hasChiNode(_, getOldInstruction(instruction)))
259197
then
260-
result = getChiInstruction(getOldInstruction(instruction)) and
198+
result = Chi(getOldInstruction(instruction)) and
261199
kind instanceof GotoEdge
262200
else (
263201
exists(OldInstruction oldInstruction |
264202
oldInstruction = getOldInstruction(instruction) and
265203
(
266204
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) then (
267-
result.getTag() = UnreachedTag() and
268-
result.getFunction() = instruction.getFunction()
205+
result = Unreached(instruction.getFunction())
269206
)
270207
else (
271208
result = getNewInstruction(oldInstruction.getSuccessor(kind))
272209
)
273210
)
274211
) or
275212
exists(OldInstruction oldInstruction |
276-
instruction = getChiInstruction(oldInstruction) and
213+
instruction = Chi(oldInstruction) and
277214
result = getNewInstruction(oldInstruction.getSuccessor(kind))
278215
)
279216
)
@@ -291,11 +228,88 @@ cached private module Cached {
291228
// `oldInstruction`, in which case the back edge should come out of the
292229
// chi node instead.
293230
if hasChiNode(_, oldInstruction)
294-
then instruction = getChiInstruction(oldInstruction)
231+
then instruction = Chi(oldInstruction)
295232
else instruction = getNewInstruction(oldInstruction)
296233
)
297234
}
298235

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+
299313
cached IRVariable getInstructionVariable(Instruction instruction) {
300314
result = getNewIRVariable(getOldInstruction(instruction).(OldIR::VariableInstruction).getVariable())
301315
}
@@ -346,7 +360,7 @@ cached private module Cached {
346360
)
347361
or
348362
exists(OldIR::Instruction oldInstruction |
349-
instruction.getTag() = ChiTag(oldInstruction) and
363+
instruction = Chi(oldInstruction) and
350364
result = getNewInstruction(oldInstruction)
351365
)
352366
}
@@ -541,11 +555,11 @@ cached private module CachedForDebugging {
541555
result = "NonSSA: " + oldInstr.getUniqueId()
542556
) or
543557
exists(Alias::VirtualVariable vvar, OldBlock phiBlock |
544-
instr.getTag() = PhiTag(vvar, phiBlock) and
558+
instr = Phi(phiBlock, vvar) and
545559
result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId()
546560
) or
547561
(
548-
instr.getTag() = UnreachedTag() and
562+
instr = Unreached(_) and
549563
result = "Unreached"
550564
)
551565
}

0 commit comments

Comments
 (0)