C++: Make sure there's a Instruction for each Expr

This change ensures that all `Expr`s (except parentheses) have a
`TranslatedExpr` with a `getResult` that's one of its own instructions,
not an instruction from one of its operands. This means that when we
translate back and forth between `Expr` and `Instruction`, like in
`DataFlow::exprNode`, we will not conflate `e` with `&e` or `... = e`.
This commit is contained in:
Jonas Jensen
2019-09-23 14:51:59 +02:00
parent 825a3d2917
commit cd5f3b84a8
7 changed files with 2072 additions and 1570 deletions

View File

@@ -44,6 +44,7 @@ newtype TInstructionTag =
ConditionValueResultLoadTag() or
BoolConversionConstantTag() or
BoolConversionCompareTag() or
ResultCopyTag() or
LoadTag() or // Implicit load due to lvalue-to-rvalue conversion
CatchTag() or
ThrowTag() or

View File

@@ -8,6 +8,7 @@ private import InstructionTag
private import TranslatedCondition
private import TranslatedFunction
private import TranslatedStmt
private import TranslatedExpr
private import IRConstruction
/**
@@ -235,6 +236,15 @@ newtype TTranslatedElement =
expr.hasLValueToRValueConversion() and
not ignoreLoad(expr)
} or
TTranslatedResultCopy(Expr expr) {
not ignoreExpr(expr) and
exprNeedsCopyIfNotLoaded(expr) and
// Doesn't have a TTranslatedLoad
not (
expr.hasLValueToRValueConversion() and
not ignoreLoad(expr)
)
} or
// An expression most naturally translated as control flow.
TTranslatedNativeCondition(Expr expr) {
not ignoreExpr(expr) and

View File

@@ -85,11 +85,14 @@ abstract class TranslatedCoreExpr extends TranslatedExpr {
final override predicate producesExprResult() {
// If there's no load, then this is the only TranslatedExpr for this
// expression.
not expr.hasLValueToRValueConversion()
or
// If we're supposed to ignore the load on this expression, then this
// is the only TranslatedExpr.
ignoreLoad(expr)
not hasLoad() and
// If there's a result copy, then this expression's result is the copy.
not exprNeedsCopyIfNotLoaded(expr)
}
private predicate hasLoad() {
expr.hasLValueToRValueConversion() and
not ignoreLoad(expr)
}
/**
@@ -106,7 +109,7 @@ abstract class TranslatedCoreExpr extends TranslatedExpr {
or
// If this TranslatedExpr doesn't produce the result, then it must represent
// a glvalue that is then loaded by a TranslatedLoad.
not producesExprResult()
hasLoad()
then result = true
else result = false
}
@@ -302,6 +305,51 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad {
private TranslatedCoreExpr getOperand() { result.getExpr() = expr }
}
/**
* IR translation of an implicit lvalue-to-rvalue conversion on the result of
* an expression.
*/
class TranslatedResultCopy extends TranslatedExpr, TTranslatedResultCopy {
TranslatedResultCopy() { this = TTranslatedResultCopy(expr) }
override string toString() { result = "Result of " + expr.toString() }
override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() }
override TranslatedElement getChild(int id) { id = 0 and result = getOperand() }
override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
) {
tag = ResultCopyTag() and
opcode instanceof Opcode::CopyValue and
resultType = getOperand().getResultType() and
isGLValue = getOperand().isResultGLValue()
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = ResultCopyTag() and
result = getParent().getChildSuccessor(this) and
kind instanceof GotoEdge
}
override Instruction getChildSuccessor(TranslatedElement child) {
child = getOperand() and result = getInstruction(ResultCopyTag())
}
override Instruction getResult() { result = getInstruction(ResultCopyTag()) }
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = ResultCopyTag() and
operandTag instanceof UnaryOperandTag and
result = getOperand().getResult()
}
final override predicate producesExprResult() { any() }
private TranslatedCoreExpr getOperand() { result.getExpr() = expr }
}
class TranslatedCommaExpr extends TranslatedNonConstantExpr {
override CommaExpr expr;
@@ -2485,3 +2533,37 @@ class TranslatedErrorExpr extends TranslatedSingleInstructionExpr {
final override Opcode getOpcode() { result instanceof Opcode::Error }
}
/**
* Holds if the translation of `expr` will not directly generate any
* `Instruction` for use as result. For such instructions we can synthesize a
* `CopyValue` instruction to ensure that there is a 1-to-1 mapping between
* expressions and result-bearing instructions.
*/
// This should ideally be a dispatch predicate on TranslatedNonConstantExpr,
// but it doesn't look monotonic to QL.
predicate exprNeedsCopyIfNotLoaded(Expr expr) {
expr instanceof AssignExpr
or
expr instanceof AssignOperation and
not expr.isPRValueCategory() // is C++
or
expr instanceof PrefixCrementOperation and
not expr.isPRValueCategory() // is C++
or
expr instanceof PointerDereferenceExpr
or
expr instanceof AddressOfExpr
or
expr instanceof BuiltInOperationBuiltInAddressOf
// No case for ParenthesisExpr to avoid getting too many instructions
or
expr instanceof ReferenceDereferenceExpr
or
expr instanceof ReferenceToExpr
or
expr instanceof CommaExpr
or
expr instanceof ConditionDeclExpr
// TODO: simplify TranslatedStmtExpr too
}

View File

@@ -1,47 +1,105 @@
| escape.cpp:108:5:108:11 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:109:5:109:13 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:110:5:110:19 | CopyValue | no_result+0:0 | no_result+0:0 |
| escape.cpp:111:5:111:21 | CopyValue | no_result+0:0 | no_result+0:0 |
| escape.cpp:111:18:111:21 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:114:5:114:8 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:115:5:115:29 | CopyValue | no_result+0:0 | no_result+0:0 |
| escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0:0 | no_+0:0 |
| escape.cpp:115:20:115:23 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:116:5:116:29 | CopyValue | no_result+0:0 | no_result+0:0 |
| escape.cpp:116:19:116:28 | PointerSub[4] | no_+0:0 | no_+0:0 |
| escape.cpp:116:20:116:23 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:117:5:117:27 | CopyValue | no_result+0:0 | no_result+0:0 |
| escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0:0 | no_+0:0 |
| escape.cpp:117:23:117:26 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:118:9:118:12 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:120:12:120:15 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:123:14:123:17 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:124:9:124:12 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:124:15:124:18 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:124:21:124:24 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:127:9:127:12 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:129:12:129:15 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:134:5:134:18 | Convert | no_Array+0:0 | no_Array+0:0 |
| escape.cpp:134:11:134:18 | Convert | no_Array+0:0 | no_Array+0:0 |
| escape.cpp:135:5:135:12 | Convert | no_Array+0:0 | no_Array+0:0 |
| escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
| escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
| escape.cpp:136:7:136:14 | Convert | no_Array+0:0 | no_Array+0:0 |
| escape.cpp:137:5:137:27 | CopyValue | no_result+0:0 | no_result+0:0 |
| escape.cpp:137:17:137:24 | Convert | no_Array+0:0 | no_Array+0:0 |
| escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
| escape.cpp:138:5:138:27 | CopyValue | no_result+0:0 | no_result+0:0 |
| escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
| escape.cpp:138:19:138:26 | Convert | no_Array+0:0 | no_Array+0:0 |
| escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 |
| escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
| escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 |
| escape.cpp:142:5:142:21 | CopyValue | no_Point+4:0 | no_Point+4:0 |
| escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
| escape.cpp:143:19:143:27 | CopyValue | no_Point+0:0 | no_Point+0:0 |
| escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
| escape.cpp:144:5:144:25 | CopyValue | no_Point+4:0 | no_Point+4:0 |
| escape.cpp:144:6:144:14 | CopyValue | no_Point+0:0 | no_Point+0:0 |
| escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
| escape.cpp:145:20:145:30 | CopyValue | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:146:5:146:18 | CopyValue | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:146:5:146:25 | CopyValue | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:146:7:146:17 | CopyValue | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:149:5:149:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:149:5:149:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:149:5:149:20 | CopyValue | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:150:18:150:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:150:18:150:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:151:5:151:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 |
| escape.cpp:151:5:151:21 | CopyValue | no_Derived+16:0 | no_Derived+16:0 |
| escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 |
| escape.cpp:152:19:152:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 |
| escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 |
| escape.cpp:155:17:155:30 | CopyValue | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 |
| escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 |
| escape.cpp:158:17:158:28 | CopyValue | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 |
| escape.cpp:158:17:158:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 |
| escape.cpp:161:19:161:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 |
| escape.cpp:161:19:161:45 | CopyValue | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 |
| escape.cpp:161:19:161:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 |
| escape.cpp:161:19:161:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 |
| escape.cpp:164:24:164:40 | CopyValue | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 |
| escape.cpp:164:24:164:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 |
| escape.cpp:167:19:167:28 | CopyValue | passByPtr+0:0 | passByPtr+0:0 |
| escape.cpp:170:21:170:29 | CopyValue | passByRef+0:0 | passByRef+0:0 |
| escape.cpp:173:22:173:38 | CopyValue | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 |
| escape.cpp:176:24:176:39 | CopyValue | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 |
| escape.cpp:179:22:179:42 | CopyValue | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 |
| escape.cpp:182:24:182:43 | CopyValue | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 |
| escape.cpp:185:30:185:40 | CopyValue | passByPtr2+0:0 | passByPtr2+0:0 |
| escape.cpp:188:32:188:41 | CopyValue | passByRef2+0:0 | passByRef2+0:0 |
| escape.cpp:191:30:191:42 | Call | none | passByPtr3+0:0 |
| escape.cpp:191:44:191:54 | CopyValue | passByPtr3+0:0 | passByPtr3+0:0 |
| escape.cpp:194:32:194:46 | Call | none | passByRef3+0:0 |
| escape.cpp:194:32:194:59 | CopyValue | none | passByRef3+0:0 |
| escape.cpp:194:48:194:57 | CopyValue | passByRef3+0:0 | passByRef3+0:0 |
| escape.cpp:199:17:199:34 | CopyValue | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 |
| escape.cpp:199:37:199:54 | CopyValue | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 |
| escape.cpp:202:5:202:19 | Call | none | passByRef6+0:0 |
| escape.cpp:202:5:202:32 | CopyValue | none | passByRef6+0:0 |
| escape.cpp:202:21:202:30 | CopyValue | passByRef6+0:0 | passByRef6+0:0 |
| escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+0:0 |
| escape.cpp:205:5:205:39 | CopyValue | none | no_ssa_passByRef7+0:0 |
| escape.cpp:205:21:205:37 | CopyValue | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 |
| escape.cpp:209:14:209:25 | Call | none | no_ssa_c+0:0 |
| escape.cpp:217:14:217:16 | CopyValue | c2+0:0 | c2+0:0 |
| escape.cpp:221:8:221:19 | Call | none | c3+0:0 |
| escape.cpp:225:17:225:28 | Call | none | c4+0:0 |
| escape.cpp:247:2:247:27 | CopyValue | no_condTemp+0:0 | no_condTemp+0:0 |
| escape.cpp:247:2:247:27 | Store | condEscape1+0:0 | condEscape1+0:0 |
| escape.cpp:247:16:247:27 | CopyValue | condEscape1+0:0 | condEscape1+0:0 |
| escape.cpp:249:9:249:34 | CopyValue | no_condTemp+0:0 | no_condTemp+0:0 |
| escape.cpp:249:9:249:34 | Store | condEscape2+0:0 | condEscape2+0:0 |
| escape.cpp:249:23:249:34 | CopyValue | condEscape2+0:0 | condEscape2+0:0 |

File diff suppressed because it is too large Load Diff

View File

@@ -211,8 +211,10 @@ ssa.cpp:
# 70| r1_3(int) = Constant[1] :
# 70| r1_4(char *) = PointerAdd[1] : r1_2, r1_3
# 70| m1_5(char *) = Store : &:r1_1, r1_4
# 70| m1_6(char) = Store : &:r1_2, r1_0
# 70| m1_7(unknown) = Chi : total:m3_0, partial:m1_6
# 70| r1_6(glval<char>) = CopyValue : r1_2
# 70| m1_7(char) = Store : &:r1_6, r1_0
# 70| m1_8(unknown) = Chi : total:m3_0, partial:m1_7
# 70| r1_9(glval<char>) = CopyValue : r1_6
#-----| Goto (back edge) -> Block 3
# 71| Block 2
@@ -222,7 +224,7 @@ ssa.cpp:
# 68| v2_3(void) = ExitFunction :
# 69| Block 3
# 69| m3_0(unknown) = Phi : from 0:~m0_1, from 1:~m1_7
# 69| m3_0(unknown) = Phi : from 0:~m0_1, from 1:~m1_8
# 69| m3_1(int) = Phi : from 0:m0_4, from 1:m3_7
# 69| m3_2(char *) = Phi : from 0:m0_6, from 1:m1_5
# 69| r3_3(glval<int>) = VariableAddress[n] :
@@ -262,20 +264,23 @@ ssa.cpp:
# 80| r1_0(int) = Constant[3] :
# 80| r1_1(glval<int>) = VariableAddress[x] :
# 80| m1_2(int) = Store : &:r1_1, r1_0
# 81| r1_3(int) = Constant[4] :
# 81| r1_4(glval<int>) = VariableAddress[y] :
# 81| m1_5(int) = Store : &:r1_4, r1_3
# 80| r1_3(glval<int>) = CopyValue : r1_1
# 81| r1_4(int) = Constant[4] :
# 81| r1_5(glval<int>) = VariableAddress[y] :
# 81| m1_6(int) = Store : &:r1_5, r1_4
# 81| r1_7(glval<int>) = CopyValue : r1_5
#-----| Goto -> Block 3
# 84| Block 2
# 84| r2_0(int) = Constant[5] :
# 84| r2_1(glval<int>) = VariableAddress[x] :
# 84| m2_2(int) = Store : &:r2_1, r2_0
# 84| r2_3(glval<int>) = CopyValue : r2_1
#-----| Goto -> Block 3
# 86| Block 3
# 86| m3_0(int) = Phi : from 1:m1_2, from 2:m2_2
# 86| m3_1(int) = Phi : from 1:m1_5, from 2:m0_10
# 86| m3_1(int) = Phi : from 1:m1_6, from 2:m0_10
# 86| r3_2(glval<int>) = VariableAddress[x_merge] :
# 86| r3_3(glval<int>) = VariableAddress[x] :
# 86| r3_4(int) = Load : &:r3_3, m3_0
@@ -323,14 +328,15 @@ ssa.cpp:
# 96| m0_9(Point) = Store : &:r0_6, r0_8
# 97| r0_10(glval<unknown>) = FunctionAddress[Escape] :
# 97| r0_11(glval<Point>) = VariableAddress[a] :
# 97| r0_12(void *) = Convert : r0_11
# 97| v0_13(void) = Call : func:r0_10, 0:r0_12
# 97| m0_14(unknown) = ^CallSideEffect : ~m0_5
# 97| m0_15(unknown) = Chi : total:m0_5, partial:m0_14
# 98| v0_16(void) = NoOp :
# 95| v0_17(void) = ReturnVoid :
# 95| v0_18(void) = UnmodeledUse : mu*
# 95| v0_19(void) = ExitFunction :
# 97| r0_12(Point *) = CopyValue : r0_11
# 97| r0_13(void *) = Convert : r0_12
# 97| v0_14(void) = Call : func:r0_10, 0:r0_13
# 97| m0_15(unknown) = ^CallSideEffect : ~m0_5
# 97| m0_16(unknown) = Chi : total:m0_5, partial:m0_15
# 98| v0_17(void) = NoOp :
# 95| v0_18(void) = ReturnVoid :
# 95| v0_19(void) = UnmodeledUse : mu*
# 95| v0_20(void) = ExitFunction :
# 100| void MustTotallyOverlap(Point)
# 100| Block 0
@@ -374,14 +380,15 @@ ssa.cpp:
# 107| m0_15(int) = Store : &:r0_11, r0_14
# 108| r0_16(glval<unknown>) = FunctionAddress[Escape] :
# 108| r0_17(glval<Point>) = VariableAddress[a] :
# 108| r0_18(void *) = Convert : r0_17
# 108| v0_19(void) = Call : func:r0_16, 0:r0_18
# 108| m0_20(unknown) = ^CallSideEffect : ~m0_5
# 108| m0_21(unknown) = Chi : total:m0_5, partial:m0_20
# 109| v0_22(void) = NoOp :
# 105| v0_23(void) = ReturnVoid :
# 105| v0_24(void) = UnmodeledUse : mu*
# 105| v0_25(void) = ExitFunction :
# 108| r0_18(Point *) = CopyValue : r0_17
# 108| r0_19(void *) = Convert : r0_18
# 108| v0_20(void) = Call : func:r0_16, 0:r0_19
# 108| m0_21(unknown) = ^CallSideEffect : ~m0_5
# 108| m0_22(unknown) = Chi : total:m0_5, partial:m0_21
# 109| v0_23(void) = NoOp :
# 105| v0_24(void) = ReturnVoid :
# 105| v0_25(void) = UnmodeledUse : mu*
# 105| v0_26(void) = ExitFunction :
# 111| void MayPartiallyOverlap(int, int)
# 111| Block 0
@@ -441,14 +448,15 @@ ssa.cpp:
# 118| m0_23(Point) = Store : &:r0_20, r0_22
# 119| r0_24(glval<unknown>) = FunctionAddress[Escape] :
# 119| r0_25(glval<Point>) = VariableAddress[a] :
# 119| r0_26(void *) = Convert : r0_25
# 119| v0_27(void) = Call : func:r0_24, 0:r0_26
# 119| m0_28(unknown) = ^CallSideEffect : ~m0_19
# 119| m0_29(unknown) = Chi : total:m0_19, partial:m0_28
# 120| v0_30(void) = NoOp :
# 116| v0_31(void) = ReturnVoid :
# 116| v0_32(void) = UnmodeledUse : mu*
# 116| v0_33(void) = ExitFunction :
# 119| r0_26(Point *) = CopyValue : r0_25
# 119| r0_27(void *) = Convert : r0_26
# 119| v0_28(void) = Call : func:r0_24, 0:r0_27
# 119| m0_29(unknown) = ^CallSideEffect : ~m0_19
# 119| m0_30(unknown) = Chi : total:m0_19, partial:m0_29
# 120| v0_31(void) = NoOp :
# 116| v0_32(void) = ReturnVoid :
# 116| v0_33(void) = UnmodeledUse : mu*
# 116| v0_34(void) = ExitFunction :
# 122| void MergeMustExactlyOverlap(bool, int, int)
# 122| Block 0
@@ -484,6 +492,7 @@ ssa.cpp:
# 125| r1_3(glval<int>) = FieldAddress[x] : r1_2
# 125| m1_4(int) = Store : &:r1_3, r1_1
# 125| m1_5(Point) = Chi : total:m0_18, partial:m1_4
# 125| r1_6(glval<int>) = CopyValue : r1_3
#-----| Goto -> Block 3
# 128| Block 2
@@ -493,6 +502,7 @@ ssa.cpp:
# 128| r2_3(glval<int>) = FieldAddress[x] : r2_2
# 128| m2_4(int) = Store : &:r2_3, r2_1
# 128| m2_5(Point) = Chi : total:m0_18, partial:m2_4
# 128| r2_6(glval<int>) = CopyValue : r2_3
#-----| Goto -> Block 3
# 130| Block 3
@@ -546,6 +556,7 @@ ssa.cpp:
# 137| r1_3(glval<int>) = FieldAddress[x] : r1_2
# 137| m1_4(int) = Store : &:r1_3, r1_1
# 137| m1_5(Point) = Chi : total:m0_18, partial:m1_4
# 137| r1_6(glval<int>) = CopyValue : r1_3
#-----| Goto -> Block 3
# 140| Block 2
@@ -553,6 +564,7 @@ ssa.cpp:
# 140| r2_1(Point) = Load : &:r2_0, m0_6
# 140| r2_2(glval<Point>) = VariableAddress[a] :
# 140| m2_3(Point) = Store : &:r2_2, r2_1
# 140| r2_4(glval<Point>) = CopyValue : r2_2
#-----| Goto -> Block 3
# 142| Block 3
@@ -602,6 +614,7 @@ ssa.cpp:
# 148| r1_3(glval<int>) = FieldAddress[x] : r1_2
# 148| m1_4(int) = Store : &:r1_3, r1_1
# 148| m1_5(Point) = Chi : total:m0_18, partial:m1_4
# 148| r1_6(glval<int>) = CopyValue : r1_3
#-----| Goto -> Block 3
# 151| Block 2
@@ -609,6 +622,7 @@ ssa.cpp:
# 151| r2_1(Point) = Load : &:r2_0, m0_6
# 151| r2_2(glval<Point>) = VariableAddress[a] :
# 151| m2_3(Point) = Store : &:r2_2, r2_1
# 151| r2_4(glval<Point>) = CopyValue : r2_2
#-----| Goto -> Block 3
# 153| Block 3
@@ -657,6 +671,7 @@ ssa.cpp:
# 159| r1_4(glval<int>) = FieldAddress[x] : r1_3
# 159| m1_5(int) = Store : &:r1_4, r1_1
# 159| m1_6(Rect) = Chi : total:m0_18, partial:m1_5
# 159| r1_7(glval<int>) = CopyValue : r1_4
#-----| Goto -> Block 3
# 162| Block 2
@@ -664,6 +679,7 @@ ssa.cpp:
# 162| r2_1(Rect) = Load : &:r2_0, m0_6
# 162| r2_2(glval<Rect>) = VariableAddress[a] :
# 162| m2_3(Rect) = Store : &:r2_2, r2_1
# 162| r2_4(glval<Rect>) = CopyValue : r2_2
#-----| Goto -> Block 3
# 164| Block 3
@@ -698,19 +714,22 @@ ssa.cpp:
# 174| r0_15(glval<Wrapper>) = VariableAddress[w] :
# 174| r0_16(glval<int>) = FieldAddress[f] : r0_15
# 174| m0_17(int) = Store : &:r0_16, r0_14
# 175| r0_18(glval<Wrapper>) = VariableAddress[w] :
# 175| r0_19(glval<int>) = FieldAddress[f] : r0_18
# 175| r0_20(int) = Load : &:r0_19, m0_17
# 175| r0_21(glval<int>) = VariableAddress[a] :
# 175| m0_22(int) = Store : &:r0_21, r0_20
# 176| r0_23(glval<Wrapper>) = VariableAddress[w] :
# 176| r0_24(Wrapper) = Load : &:r0_23, ~m0_17
# 176| r0_25(glval<Wrapper>) = VariableAddress[x] :
# 176| m0_26(Wrapper) = Store : &:r0_25, r0_24
# 177| v0_27(void) = NoOp :
# 171| v0_28(void) = ReturnVoid :
# 171| v0_29(void) = UnmodeledUse : mu*
# 171| v0_30(void) = ExitFunction :
# 174| r0_18(glval<int>) = CopyValue : r0_16
# 175| r0_19(glval<Wrapper>) = VariableAddress[w] :
# 175| r0_20(glval<int>) = FieldAddress[f] : r0_19
# 175| r0_21(int) = Load : &:r0_20, m0_17
# 175| r0_22(glval<int>) = VariableAddress[a] :
# 175| m0_23(int) = Store : &:r0_22, r0_21
# 175| r0_24(glval<int>) = CopyValue : r0_22
# 176| r0_25(glval<Wrapper>) = VariableAddress[w] :
# 176| r0_26(Wrapper) = Load : &:r0_25, ~m0_17
# 176| r0_27(glval<Wrapper>) = VariableAddress[x] :
# 176| m0_28(Wrapper) = Store : &:r0_27, r0_26
# 176| r0_29(glval<Wrapper>) = CopyValue : r0_27
# 177| v0_30(void) = NoOp :
# 171| v0_31(void) = ReturnVoid :
# 171| v0_32(void) = UnmodeledUse : mu*
# 171| v0_33(void) = ExitFunction :
# 179| int AsmStmt(int*)
# 179| Block 0
@@ -791,19 +810,21 @@ ssa.cpp:
# 200| r0_27(int) = Load : &:r0_26, m0_19
# 200| r0_28(int) = Add : r0_27, r0_24
# 200| m0_29(int) = Store : &:r0_26, r0_28
# 201| r0_30(glval<unknown>) = FunctionAddress[abs] :
# 201| r0_31(glval<int>) = VariableAddress[x] :
# 201| r0_32(int) = Load : &:r0_31, m0_8
# 201| r0_33(int) = Call : func:r0_30, 0:r0_32
# 201| r0_34(glval<int>) = VariableAddress[ret] :
# 201| r0_35(int) = Load : &:r0_34, m0_29
# 201| r0_36(int) = Add : r0_35, r0_33
# 201| m0_37(int) = Store : &:r0_34, r0_36
# 202| r0_38(glval<int>) = VariableAddress[#return] :
# 202| r0_39(glval<int>) = VariableAddress[ret] :
# 202| r0_40(int) = Load : &:r0_39, m0_37
# 202| m0_41(int) = Store : &:r0_38, r0_40
# 198| r0_42(glval<int>) = VariableAddress[#return] :
# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41
# 198| v0_44(void) = UnmodeledUse : mu*
# 198| v0_45(void) = ExitFunction :
# 200| r0_30(glval<int>) = CopyValue : r0_26
# 201| r0_31(glval<unknown>) = FunctionAddress[abs] :
# 201| r0_32(glval<int>) = VariableAddress[x] :
# 201| r0_33(int) = Load : &:r0_32, m0_8
# 201| r0_34(int) = Call : func:r0_31, 0:r0_33
# 201| r0_35(glval<int>) = VariableAddress[ret] :
# 201| r0_36(int) = Load : &:r0_35, m0_29
# 201| r0_37(int) = Add : r0_36, r0_34
# 201| m0_38(int) = Store : &:r0_35, r0_37
# 201| r0_39(glval<int>) = CopyValue : r0_35
# 202| r0_40(glval<int>) = VariableAddress[#return] :
# 202| r0_41(glval<int>) = VariableAddress[ret] :
# 202| r0_42(int) = Load : &:r0_41, m0_38
# 202| m0_43(int) = Store : &:r0_40, r0_42
# 198| r0_44(glval<int>) = VariableAddress[#return] :
# 198| v0_45(void) = ReturnValue : &:r0_44, m0_43
# 198| v0_46(void) = UnmodeledUse : mu*
# 198| v0_47(void) = ExitFunction :

View File

@@ -214,7 +214,9 @@ ssa.cpp:
# 70| r1_3(int) = Constant[1] :
# 70| r1_4(char *) = PointerAdd[1] : r1_2, r1_3
# 70| m1_5(char *) = Store : &:r1_1, r1_4
# 70| mu1_6(char) = Store : &:r1_2, r1_0
# 70| r1_6(glval<char>) = CopyValue : r1_2
# 70| mu1_7(char) = Store : &:r1_6, r1_0
# 70| r1_8(glval<char>) = CopyValue : r1_6
#-----| Goto (back edge) -> Block 3
# 71| Block 2
@@ -263,20 +265,23 @@ ssa.cpp:
# 80| r1_0(int) = Constant[3] :
# 80| r1_1(glval<int>) = VariableAddress[x] :
# 80| m1_2(int) = Store : &:r1_1, r1_0
# 81| r1_3(int) = Constant[4] :
# 81| r1_4(glval<int>) = VariableAddress[y] :
# 81| m1_5(int) = Store : &:r1_4, r1_3
# 80| r1_3(glval<int>) = CopyValue : r1_1
# 81| r1_4(int) = Constant[4] :
# 81| r1_5(glval<int>) = VariableAddress[y] :
# 81| m1_6(int) = Store : &:r1_5, r1_4
# 81| r1_7(glval<int>) = CopyValue : r1_5
#-----| Goto -> Block 3
# 84| Block 2
# 84| r2_0(int) = Constant[5] :
# 84| r2_1(glval<int>) = VariableAddress[x] :
# 84| m2_2(int) = Store : &:r2_1, r2_0
# 84| r2_3(glval<int>) = CopyValue : r2_1
#-----| Goto -> Block 3
# 86| Block 3
# 86| m3_0(int) = Phi : from 1:m1_2, from 2:m2_2
# 86| m3_1(int) = Phi : from 1:m1_5, from 2:m0_10
# 86| m3_1(int) = Phi : from 1:m1_6, from 2:m0_10
# 86| r3_2(glval<int>) = VariableAddress[x_merge] :
# 86| r3_3(glval<int>) = VariableAddress[x] :
# 86| r3_4(int) = Load : &:r3_3, m3_0
@@ -323,13 +328,14 @@ ssa.cpp:
# 96| m0_8(Point) = Store : &:r0_5, r0_7
# 97| r0_9(glval<unknown>) = FunctionAddress[Escape] :
# 97| r0_10(glval<Point>) = VariableAddress[a] :
# 97| r0_11(void *) = Convert : r0_10
# 97| v0_12(void) = Call : func:r0_9, 0:r0_11
# 97| mu0_13(unknown) = ^CallSideEffect : ~mu0_2
# 98| v0_14(void) = NoOp :
# 95| v0_15(void) = ReturnVoid :
# 95| v0_16(void) = UnmodeledUse : mu*
# 95| v0_17(void) = ExitFunction :
# 97| r0_11(Point *) = CopyValue : r0_10
# 97| r0_12(void *) = Convert : r0_11
# 97| v0_13(void) = Call : func:r0_9, 0:r0_12
# 97| mu0_14(unknown) = ^CallSideEffect : ~mu0_2
# 98| v0_15(void) = NoOp :
# 95| v0_16(void) = ReturnVoid :
# 95| v0_17(void) = UnmodeledUse : mu*
# 95| v0_18(void) = ExitFunction :
# 100| void MustTotallyOverlap(Point)
# 100| Block 0
@@ -372,13 +378,14 @@ ssa.cpp:
# 107| m0_14(int) = Store : &:r0_10, r0_13
# 108| r0_15(glval<unknown>) = FunctionAddress[Escape] :
# 108| r0_16(glval<Point>) = VariableAddress[a] :
# 108| r0_17(void *) = Convert : r0_16
# 108| v0_18(void) = Call : func:r0_15, 0:r0_17
# 108| mu0_19(unknown) = ^CallSideEffect : ~mu0_2
# 109| v0_20(void) = NoOp :
# 105| v0_21(void) = ReturnVoid :
# 105| v0_22(void) = UnmodeledUse : mu*
# 105| v0_23(void) = ExitFunction :
# 108| r0_17(Point *) = CopyValue : r0_16
# 108| r0_18(void *) = Convert : r0_17
# 108| v0_19(void) = Call : func:r0_15, 0:r0_18
# 108| mu0_20(unknown) = ^CallSideEffect : ~mu0_2
# 109| v0_21(void) = NoOp :
# 105| v0_22(void) = ReturnVoid :
# 105| v0_23(void) = UnmodeledUse : mu*
# 105| v0_24(void) = ExitFunction :
# 111| void MayPartiallyOverlap(int, int)
# 111| Block 0
@@ -433,13 +440,14 @@ ssa.cpp:
# 118| m0_20(Point) = Store : &:r0_17, r0_19
# 119| r0_21(glval<unknown>) = FunctionAddress[Escape] :
# 119| r0_22(glval<Point>) = VariableAddress[a] :
# 119| r0_23(void *) = Convert : r0_22
# 119| v0_24(void) = Call : func:r0_21, 0:r0_23
# 119| mu0_25(unknown) = ^CallSideEffect : ~mu0_2
# 120| v0_26(void) = NoOp :
# 116| v0_27(void) = ReturnVoid :
# 116| v0_28(void) = UnmodeledUse : mu*
# 116| v0_29(void) = ExitFunction :
# 119| r0_23(Point *) = CopyValue : r0_22
# 119| r0_24(void *) = Convert : r0_23
# 119| v0_25(void) = Call : func:r0_21, 0:r0_24
# 119| mu0_26(unknown) = ^CallSideEffect : ~mu0_2
# 120| v0_27(void) = NoOp :
# 116| v0_28(void) = ReturnVoid :
# 116| v0_29(void) = UnmodeledUse : mu*
# 116| v0_30(void) = ExitFunction :
# 122| void MergeMustExactlyOverlap(bool, int, int)
# 122| Block 0
@@ -472,6 +480,7 @@ ssa.cpp:
# 125| r1_2(glval<Point>) = VariableAddress[a] :
# 125| r1_3(glval<int>) = FieldAddress[x] : r1_2
# 125| mu1_4(int) = Store : &:r1_3, r1_1
# 125| r1_5(glval<int>) = CopyValue : r1_3
#-----| Goto -> Block 3
# 128| Block 2
@@ -480,6 +489,7 @@ ssa.cpp:
# 128| r2_2(glval<Point>) = VariableAddress[a] :
# 128| r2_3(glval<int>) = FieldAddress[x] : r2_2
# 128| mu2_4(int) = Store : &:r2_3, r2_1
# 128| r2_5(glval<int>) = CopyValue : r2_3
#-----| Goto -> Block 3
# 130| Block 3
@@ -528,6 +538,7 @@ ssa.cpp:
# 137| r1_2(glval<Point>) = VariableAddress[a] :
# 137| r1_3(glval<int>) = FieldAddress[x] : r1_2
# 137| mu1_4(int) = Store : &:r1_3, r1_1
# 137| r1_5(glval<int>) = CopyValue : r1_3
#-----| Goto -> Block 3
# 140| Block 2
@@ -535,6 +546,7 @@ ssa.cpp:
# 140| r2_1(Point) = Load : &:r2_0, m0_6
# 140| r2_2(glval<Point>) = VariableAddress[a] :
# 140| mu2_3(Point) = Store : &:r2_2, r2_1
# 140| r2_4(glval<Point>) = CopyValue : r2_2
#-----| Goto -> Block 3
# 142| Block 3
@@ -579,6 +591,7 @@ ssa.cpp:
# 148| r1_2(glval<Point>) = VariableAddress[a] :
# 148| r1_3(glval<int>) = FieldAddress[x] : r1_2
# 148| mu1_4(int) = Store : &:r1_3, r1_1
# 148| r1_5(glval<int>) = CopyValue : r1_3
#-----| Goto -> Block 3
# 151| Block 2
@@ -586,6 +599,7 @@ ssa.cpp:
# 151| r2_1(Point) = Load : &:r2_0, m0_6
# 151| r2_2(glval<Point>) = VariableAddress[a] :
# 151| mu2_3(Point) = Store : &:r2_2, r2_1
# 151| r2_4(glval<Point>) = CopyValue : r2_2
#-----| Goto -> Block 3
# 153| Block 3
@@ -630,6 +644,7 @@ ssa.cpp:
# 159| r1_3(glval<Point>) = FieldAddress[topLeft] : r1_2
# 159| r1_4(glval<int>) = FieldAddress[x] : r1_3
# 159| mu1_5(int) = Store : &:r1_4, r1_1
# 159| r1_6(glval<int>) = CopyValue : r1_4
#-----| Goto -> Block 3
# 162| Block 2
@@ -637,6 +652,7 @@ ssa.cpp:
# 162| r2_1(Rect) = Load : &:r2_0, m0_6
# 162| r2_2(glval<Rect>) = VariableAddress[a] :
# 162| mu2_3(Rect) = Store : &:r2_2, r2_1
# 162| r2_4(glval<Rect>) = CopyValue : r2_2
#-----| Goto -> Block 3
# 164| Block 3
@@ -670,19 +686,22 @@ ssa.cpp:
# 174| r0_15(glval<Wrapper>) = VariableAddress[w] :
# 174| r0_16(glval<int>) = FieldAddress[f] : r0_15
# 174| mu0_17(int) = Store : &:r0_16, r0_14
# 175| r0_18(glval<Wrapper>) = VariableAddress[w] :
# 175| r0_19(glval<int>) = FieldAddress[f] : r0_18
# 175| r0_20(int) = Load : &:r0_19, ~mu0_2
# 175| r0_21(glval<int>) = VariableAddress[a] :
# 175| m0_22(int) = Store : &:r0_21, r0_20
# 176| r0_23(glval<Wrapper>) = VariableAddress[w] :
# 176| r0_24(Wrapper) = Load : &:r0_23, ~mu0_2
# 176| r0_25(glval<Wrapper>) = VariableAddress[x] :
# 176| m0_26(Wrapper) = Store : &:r0_25, r0_24
# 177| v0_27(void) = NoOp :
# 171| v0_28(void) = ReturnVoid :
# 171| v0_29(void) = UnmodeledUse : mu*
# 171| v0_30(void) = ExitFunction :
# 174| r0_18(glval<int>) = CopyValue : r0_16
# 175| r0_19(glval<Wrapper>) = VariableAddress[w] :
# 175| r0_20(glval<int>) = FieldAddress[f] : r0_19
# 175| r0_21(int) = Load : &:r0_20, ~mu0_2
# 175| r0_22(glval<int>) = VariableAddress[a] :
# 175| m0_23(int) = Store : &:r0_22, r0_21
# 175| r0_24(glval<int>) = CopyValue : r0_22
# 176| r0_25(glval<Wrapper>) = VariableAddress[w] :
# 176| r0_26(Wrapper) = Load : &:r0_25, ~mu0_2
# 176| r0_27(glval<Wrapper>) = VariableAddress[x] :
# 176| m0_28(Wrapper) = Store : &:r0_27, r0_26
# 176| r0_29(glval<Wrapper>) = CopyValue : r0_27
# 177| v0_30(void) = NoOp :
# 171| v0_31(void) = ReturnVoid :
# 171| v0_32(void) = UnmodeledUse : mu*
# 171| v0_33(void) = ExitFunction :
# 179| int AsmStmt(int*)
# 179| Block 0
@@ -757,19 +776,21 @@ ssa.cpp:
# 200| r0_27(int) = Load : &:r0_26, m0_19
# 200| r0_28(int) = Add : r0_27, r0_24
# 200| m0_29(int) = Store : &:r0_26, r0_28
# 201| r0_30(glval<unknown>) = FunctionAddress[abs] :
# 201| r0_31(glval<int>) = VariableAddress[x] :
# 201| r0_32(int) = Load : &:r0_31, m0_8
# 201| r0_33(int) = Call : func:r0_30, 0:r0_32
# 201| r0_34(glval<int>) = VariableAddress[ret] :
# 201| r0_35(int) = Load : &:r0_34, m0_29
# 201| r0_36(int) = Add : r0_35, r0_33
# 201| m0_37(int) = Store : &:r0_34, r0_36
# 202| r0_38(glval<int>) = VariableAddress[#return] :
# 202| r0_39(glval<int>) = VariableAddress[ret] :
# 202| r0_40(int) = Load : &:r0_39, m0_37
# 202| m0_41(int) = Store : &:r0_38, r0_40
# 198| r0_42(glval<int>) = VariableAddress[#return] :
# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41
# 198| v0_44(void) = UnmodeledUse : mu*
# 198| v0_45(void) = ExitFunction :
# 200| r0_30(glval<int>) = CopyValue : r0_26
# 201| r0_31(glval<unknown>) = FunctionAddress[abs] :
# 201| r0_32(glval<int>) = VariableAddress[x] :
# 201| r0_33(int) = Load : &:r0_32, m0_8
# 201| r0_34(int) = Call : func:r0_31, 0:r0_33
# 201| r0_35(glval<int>) = VariableAddress[ret] :
# 201| r0_36(int) = Load : &:r0_35, m0_29
# 201| r0_37(int) = Add : r0_36, r0_34
# 201| m0_38(int) = Store : &:r0_35, r0_37
# 201| r0_39(glval<int>) = CopyValue : r0_35
# 202| r0_40(glval<int>) = VariableAddress[#return] :
# 202| r0_41(glval<int>) = VariableAddress[ret] :
# 202| r0_42(int) = Load : &:r0_41, m0_38
# 202| m0_43(int) = Store : &:r0_40, r0_42
# 198| r0_44(glval<int>) = VariableAddress[#return] :
# 198| v0_45(void) = ReturnValue : &:r0_44, m0_43
# 198| v0_46(void) = UnmodeledUse : mu*
# 198| v0_47(void) = ExitFunction :