@@ -13,6 +13,222 @@ private import TranslatedInitialization
13
13
14
14
TranslatedStmt getTranslatedStmt ( Stmt stmt ) { result .getAst ( ) = stmt }
15
15
16
+ TranslatedMicrosoftTryExceptHandler getTranslatedMicrosoftTryExceptHandler (
17
+ MicrosoftTryExceptStmt tryExcept
18
+ ) {
19
+ result .getAst ( ) = tryExcept .getExcept ( )
20
+ }
21
+
22
+ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement ,
23
+ TTranslatedMicrosoftTryExceptHandler {
24
+ MicrosoftTryExceptStmt tryExcept ;
25
+
26
+ TranslatedMicrosoftTryExceptHandler ( ) { this = TTranslatedMicrosoftTryExceptHandler ( tryExcept ) }
27
+
28
+ final override string toString ( ) { result = tryExcept .toString ( ) }
29
+
30
+ final override Locatable getAst ( ) { result = tryExcept .getExcept ( ) }
31
+
32
+ override Instruction getFirstInstruction ( ) { result = this .getChild ( 0 ) .getFirstInstruction ( ) }
33
+
34
+ override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType resultType ) {
35
+ // t1 = -1
36
+ tag = TryExceptGenerateNegativeOne ( ) and
37
+ opcode instanceof Opcode:: Constant and
38
+ resultType = getIntType ( )
39
+ or
40
+ // t2 = cmp t1, condition
41
+ tag = TryExceptCompareNegativeOne ( ) and
42
+ opcode instanceof Opcode:: CompareEQ and
43
+ resultType = getBoolType ( )
44
+ or
45
+ // if t2 goto ... else goto ...
46
+ tag = TryExceptCompareNegativeOneBranch ( ) and
47
+ opcode instanceof Opcode:: ConditionalBranch and
48
+ resultType = getVoidType ( )
49
+ or
50
+ // t1 = 0
51
+ tag = TryExceptGenerateZero ( ) and
52
+ opcode instanceof Opcode:: Constant and
53
+ resultType = getIntType ( )
54
+ or
55
+ // t2 = cmp t1, condition
56
+ tag = TryExceptCompareZero ( ) and
57
+ opcode instanceof Opcode:: CompareEQ and
58
+ resultType = getBoolType ( )
59
+ or
60
+ // if t2 goto ... else goto ...
61
+ tag = TryExceptCompareZeroBranch ( ) and
62
+ opcode instanceof Opcode:: ConditionalBranch and
63
+ resultType = getVoidType ( )
64
+ or
65
+ // t1 = 1
66
+ tag = TryExceptGenerateOne ( ) and
67
+ opcode instanceof Opcode:: Constant and
68
+ resultType = getIntType ( )
69
+ or
70
+ // t2 = cmp t1, condition
71
+ tag = TryExceptCompareOne ( ) and
72
+ opcode instanceof Opcode:: CompareEQ and
73
+ resultType = getBoolType ( )
74
+ or
75
+ // if t2 goto ... else goto ...
76
+ tag = TryExceptCompareOneBranch ( ) and
77
+ opcode instanceof Opcode:: ConditionalBranch and
78
+ resultType = getVoidType ( )
79
+ or
80
+ // unwind stack
81
+ tag = UnwindTag ( ) and
82
+ opcode instanceof Opcode:: Unwind and
83
+ resultType = getVoidType ( )
84
+ }
85
+
86
+ final override Instruction getInstructionRegisterOperand ( InstructionTag tag , OperandTag operandTag ) {
87
+ tag = TryExceptCompareNegativeOne ( ) and
88
+ (
89
+ operandTag instanceof LeftOperandTag and
90
+ result = this .getTranslatedCondition ( ) .getResult ( )
91
+ or
92
+ operandTag instanceof RightOperandTag and
93
+ result = this .getInstruction ( TryExceptGenerateNegativeOne ( ) )
94
+ )
95
+ or
96
+ tag = TryExceptCompareNegativeOneBranch ( ) and
97
+ operandTag instanceof ConditionOperandTag and
98
+ result = this .getInstruction ( TryExceptCompareNegativeOne ( ) )
99
+ or
100
+ tag = TryExceptCompareZero ( ) and
101
+ (
102
+ operandTag instanceof LeftOperandTag and
103
+ result = this .getTranslatedCondition ( ) .getResult ( )
104
+ or
105
+ operandTag instanceof RightOperandTag and
106
+ result = this .getInstruction ( TryExceptGenerateZero ( ) )
107
+ )
108
+ or
109
+ tag = TryExceptCompareZeroBranch ( ) and
110
+ operandTag instanceof ConditionOperandTag and
111
+ result = this .getInstruction ( TryExceptCompareZero ( ) )
112
+ or
113
+ tag = TryExceptCompareOne ( ) and
114
+ (
115
+ operandTag instanceof LeftOperandTag and
116
+ result = this .getTranslatedCondition ( ) .getResult ( )
117
+ or
118
+ operandTag instanceof RightOperandTag and
119
+ result = this .getInstruction ( TryExceptGenerateOne ( ) )
120
+ )
121
+ or
122
+ tag = TryExceptCompareOneBranch ( ) and
123
+ operandTag instanceof ConditionOperandTag and
124
+ result = this .getInstruction ( TryExceptCompareOne ( ) )
125
+ }
126
+
127
+ override string getInstructionConstantValue ( InstructionTag tag ) {
128
+ tag = TryExceptGenerateNegativeOne ( ) and
129
+ result = "-1"
130
+ or
131
+ tag = TryExceptGenerateZero ( ) and
132
+ result = "0"
133
+ or
134
+ tag = TryExceptGenerateOne ( ) and
135
+ result = "1"
136
+ }
137
+
138
+ override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) {
139
+ // Generate -1 -> Compare condition
140
+ tag = TryExceptGenerateNegativeOne ( ) and
141
+ kind instanceof GotoEdge and
142
+ result = this .getInstruction ( TryExceptCompareNegativeOne ( ) )
143
+ or
144
+ // Compare condition -> Branch
145
+ tag = TryExceptCompareNegativeOne ( ) and
146
+ kind instanceof GotoEdge and
147
+ result = this .getInstruction ( TryExceptCompareNegativeOneBranch ( ) )
148
+ or
149
+ // Branch -> Unwind or Generate 0
150
+ tag = TryExceptCompareNegativeOneBranch ( ) and
151
+ (
152
+ kind instanceof TrueEdge and
153
+ // TODO: This is not really correct. The semantics of `EXCEPTION_CONTINUE_EXECUTION` is that
154
+ // we should continue execution at the point where the exception occurred. But we don't have
155
+ // any instruction to model this behavior.
156
+ result = this .getInstruction ( UnwindTag ( ) )
157
+ or
158
+ kind instanceof FalseEdge and
159
+ result = this .getInstruction ( TryExceptGenerateZero ( ) )
160
+ )
161
+ or
162
+ // Generate 0 -> Compare condition
163
+ tag = TryExceptGenerateZero ( ) and
164
+ kind instanceof GotoEdge and
165
+ result = this .getInstruction ( TryExceptCompareZero ( ) )
166
+ or
167
+ // Compare condition -> Branch
168
+ tag = TryExceptCompareZero ( ) and
169
+ kind instanceof GotoEdge and
170
+ result = this .getInstruction ( TryExceptCompareZeroBranch ( ) )
171
+ or
172
+ // Branch -> Unwind or Generate 1
173
+ tag = TryExceptCompareZeroBranch ( ) and
174
+ (
175
+ kind instanceof TrueEdge and
176
+ result = this .getInstruction ( UnwindTag ( ) )
177
+ or
178
+ kind instanceof FalseEdge and
179
+ result = this .getInstruction ( TryExceptGenerateOne ( ) )
180
+ )
181
+ or
182
+ // Generate 1 -> Compare condition
183
+ tag = TryExceptGenerateOne ( ) and
184
+ kind instanceof GotoEdge and
185
+ result = this .getInstruction ( TryExceptCompareOne ( ) )
186
+ or
187
+ // Compare condition -> Branch
188
+ tag = TryExceptCompareOne ( ) and
189
+ kind instanceof GotoEdge and
190
+ result = this .getInstruction ( TryExceptCompareOneBranch ( ) )
191
+ or
192
+ // Branch -> Handler (the condition value is always 0, -1 or 1, and we've checked for 0 or -1 already.)
193
+ tag = TryExceptCompareOneBranch ( ) and
194
+ (
195
+ kind instanceof TrueEdge and
196
+ result = this .getTranslatedHandler ( ) .getFirstInstruction ( )
197
+ )
198
+ or
199
+ // Unwind -> Parent
200
+ tag = UnwindTag ( ) and
201
+ kind instanceof GotoEdge and
202
+ result = this .getParent ( ) .getChildSuccessor ( this )
203
+ }
204
+
205
+ override Instruction getChildSuccessor ( TranslatedElement child ) {
206
+ child = this .getTranslatedCondition ( ) and
207
+ result = this .getInstruction ( TryExceptGenerateNegativeOne ( ) )
208
+ or
209
+ child = this .getTranslatedHandler ( ) and
210
+ result = this .getParent ( ) .getChildSuccessor ( this )
211
+ }
212
+
213
+ private TranslatedExpr getTranslatedCondition ( ) {
214
+ result = getTranslatedExpr ( tryExcept .getCondition ( ) )
215
+ }
216
+
217
+ private TranslatedStmt getTranslatedHandler ( ) {
218
+ result = getTranslatedStmt ( tryExcept .getExcept ( ) )
219
+ }
220
+
221
+ override TranslatedElement getChild ( int id ) {
222
+ id = 0 and
223
+ result = this .getTranslatedCondition ( )
224
+ or
225
+ id = 1 and
226
+ result = this .getTranslatedHandler ( )
227
+ }
228
+
229
+ final override Function getFunction ( ) { result = tryExcept .getEnclosingFunction ( ) }
230
+ }
231
+
16
232
abstract class TranslatedStmt extends TranslatedElement , TTranslatedStmt {
17
233
Stmt stmt ;
18
234
@@ -249,15 +465,57 @@ class TranslatedUnreachableReturnStmt extends TranslatedReturnStmt {
249
465
}
250
466
251
467
/**
252
- * The IR translation of a C++ `try` statement.
468
+ * A C/C++ `try` statement, or a `__try __except` or `__try __finally` statement.
469
+ */
470
+ private class TryOrMicrosoftTryStmt extends Stmt {
471
+ TryOrMicrosoftTryStmt ( ) {
472
+ this instanceof TryStmt or
473
+ this instanceof MicrosoftTryStmt
474
+ }
475
+
476
+ /** Gets the number of `catch block`s of this statement. */
477
+ int getNumberOfCatchClauses ( ) {
478
+ result = this .( TryStmt ) .getNumberOfCatchClauses ( )
479
+ or
480
+ this instanceof MicrosoftTryExceptStmt and
481
+ result = 1
482
+ or
483
+ this instanceof MicrosoftTryFinallyStmt and
484
+ result = 0
485
+ }
486
+
487
+ /** Gets the `body` statement of this statement. */
488
+ Stmt getStmt ( ) {
489
+ result = this .( TryStmt ) .getStmt ( )
490
+ or
491
+ result = this .( MicrosoftTryStmt ) .getStmt ( )
492
+ }
493
+
494
+ /** Gets the `i`th translated handler of this statement. */
495
+ TranslatedElement getTranslatedHandler ( int index ) {
496
+ result = getTranslatedStmt ( this .( TryStmt ) .getChild ( index + 1 ) )
497
+ or
498
+ index = 0 and
499
+ result = getTranslatedMicrosoftTryExceptHandler ( this )
500
+ }
501
+
502
+ /** Gets the `finally` statement (usually a BlockStmt), if any. */
503
+ Stmt getFinally ( ) { result = this .( MicrosoftTryFinallyStmt ) .getFinally ( ) }
504
+ }
505
+
506
+ /**
507
+ * The IR translation of a C++ `try` (or a `__try __except` or `__try __finally`) statement.
253
508
*/
254
509
class TranslatedTryStmt extends TranslatedStmt {
255
- override TryStmt stmt ;
510
+ override TryOrMicrosoftTryStmt stmt ;
256
511
257
512
override TranslatedElement getChild ( int id ) {
258
513
id = 0 and result = getBody ( )
259
514
or
260
515
result = getHandler ( id - 1 )
516
+ or
517
+ id = stmt .getNumberOfCatchClauses ( ) + 1 and
518
+ result = this .getFinally ( )
261
519
}
262
520
263
521
override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType resultType ) {
@@ -269,8 +527,20 @@ class TranslatedTryStmt extends TranslatedStmt {
269
527
override Instruction getFirstInstruction ( ) { result = getBody ( ) .getFirstInstruction ( ) }
270
528
271
529
override Instruction getChildSuccessor ( TranslatedElement child ) {
272
- // All children go to the successor of the `try`.
273
- child = getAChild ( ) and result = getParent ( ) .getChildSuccessor ( this )
530
+ // All non-finally children go to the successor of the `try` if
531
+ // there is no finally block, but if there is a finally block
532
+ // then we go to that one.
533
+ child = [ this .getBody ( ) , this .getHandler ( _) ] and
534
+ (
535
+ not exists ( this .getFinally ( ) ) and
536
+ result = this .getParent ( ) .getChildSuccessor ( this )
537
+ or
538
+ result = this .getFinally ( ) .getFirstInstruction ( )
539
+ )
540
+ or
541
+ // And after the finally block we go to the successor of the `try`.
542
+ child = this .getFinally ( ) and
543
+ result = this .getParent ( ) .getChildSuccessor ( this )
274
544
}
275
545
276
546
final Instruction getNextHandler ( TranslatedHandler handler ) {
@@ -290,9 +560,9 @@ class TranslatedTryStmt extends TranslatedStmt {
290
560
result = getHandler ( 0 ) .getFirstInstruction ( )
291
561
}
292
562
293
- private TranslatedHandler getHandler ( int index ) {
294
- result = getTranslatedStmt ( stmt . getChild ( index + 1 ) )
295
- }
563
+ private TranslatedElement getHandler ( int index ) { result = stmt . getTranslatedHandler ( index ) }
564
+
565
+ private TranslatedStmt getFinally ( ) { result = getTranslatedStmt ( stmt . getFinally ( ) ) }
296
566
297
567
private TranslatedStmt getBody ( ) { result = getTranslatedStmt ( stmt .getStmt ( ) ) }
298
568
}
0 commit comments