C++: Fix handling of accesses to escaped variables in Aliased SSA

This fixes a subtle bug in the construction of aliased SSA. `getResultMemoryAccess` was failing to return a `MemoryAccess` for a store to a variable whose address escaped. This is because no `VirtualIRVariable` was being created for such variables. The code was assuming that any access to such a variable would be via `UnknownMemoryAccess`. The result is that accesses to such variables were not being modeled in SSA at all.

Instead, the way to handle this is to have a `VariableMemoryAccess` even when the variable being accessed has escaped, and to have `VariableMemoryAccess::getVirtualVariable()` return the `UnknownVirtualVariable` for escaped variables. In the future, this will also let us be less conservative about inserting `Chi` nodes, because we'll be able to determine that there's an exact overlap between two accesses to the same escaped variable in some cases.
This commit is contained in:
Dave Bartolomeo
2018-11-30 12:02:05 -08:00
parent ae8f18c0b5
commit af443569d9
3 changed files with 287 additions and 246 deletions

View File

@@ -19,6 +19,10 @@ private VirtualIRVariable getVirtualVariable(IRVariable var) {
result.getIRVariable() = var
}
private UnknownVirtualVariable getUnknownVirtualVariable(FunctionIR f) {
result.getFunctionIR() = f
}
class VirtualVariable extends TVirtualVariable {
string toString() {
none()
@@ -83,10 +87,10 @@ class UnknownVirtualVariable extends VirtualVariable, TUnknownVirtualVariable {
}
private newtype TMemoryAccess =
TVariableMemoryAccess(VirtualIRVariable vvar, IntValue offset, IntValue size) {
TVariableMemoryAccess(IRVariable var, IntValue offset, IntValue size) {
exists(Instruction instr |
exists(MemoryAccessKind mak | instr.getResultMemoryAccess() = mak and not mak instanceof PhiMemoryAccess) and
resultPointsTo(instr.getAnOperand().(AddressOperand).getDefinitionInstruction(), vvar.getIRVariable(), offset) and
resultPointsTo(instr.getAnOperand().(AddressOperand).getDefinitionInstruction(), var, offset) and
if exists(instr.getResultSize())
then instr.getResultSize() = size
else size = Ints::unknown()
@@ -97,7 +101,7 @@ private newtype TMemoryAccess =
TTotalUnknownMemoryAccess(UnknownVirtualVariable uvv)
private VariableMemoryAccess getVariableMemoryAccess(IRVariable var, IntValue offset, IntValue size) {
result.getVirtualVariable() = getVirtualVariable(var) and
result.getVariable() = var and
result.getOffset() = offset and
result.getSize() = size
}
@@ -117,20 +121,21 @@ class MemoryAccess extends TMemoryAccess {
}
class VariableMemoryAccess extends TVariableMemoryAccess, MemoryAccess {
VirtualIRVariable vvar;
IRVariable var;
IntValue offset;
IntValue size;
VariableMemoryAccess() {
this = TVariableMemoryAccess(vvar, offset, size)
this = TVariableMemoryAccess(var, offset, size)
}
override final string toString() {
result = vvar.toString()
result = var.toString() + "[" + offset.toString() + ".." + (offset + size - 1).toString() + "]"
}
final override VirtualVariable getVirtualVariable() {
result = vvar
result = getVirtualVariable(var) or
not exists(getVirtualVariable(var)) and result = getUnknownVirtualVariable(var.getFunctionIR())
}
IntValue getOffset() {
@@ -141,10 +146,15 @@ class VariableMemoryAccess extends TVariableMemoryAccess, MemoryAccess {
result = size
}
final IRVariable getVariable() {
result = var
}
final override predicate isPartialMemoryAccess() {
not exists(getVirtualVariable(var)) or
getOffset() != 0
or
getSize() != vvar.getType().getSize()
getSize() != var.getType().getSize()
}
}
@@ -166,6 +176,7 @@ class UnknownMemoryAccess extends TUnknownMemoryAccess, MemoryAccess {
final override predicate isPartialMemoryAccess() {
any()
}
Type getType() {
result instanceof UnknownType
}

View File

@@ -0,0 +1,12 @@
private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
private import AliasedSSA
/**
* Property provide that dumps the memory access of each result. Useful for debugging SSA
* construction.
*/
class PropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instruction, string key) {
key = "ResultMemoryAccess" and result = getResultMemoryAccess(instruction).toString()
}
}

View File

@@ -1,24 +1,26 @@
bad_asts.cpp:
# 14| Bad::CallBadMemberFunction() -> void
# 14| Block 0
# 14| v0_0(void) = EnterFunction :
# 14| m0_1(unknown) = AliasedDefinition :
# 14| mu0_2(unknown) = UnmodeledDefinition :
# 15| r0_3(glval<S>) = VariableAddress[s] :
# 15| mu0_4(S) = Uninitialized : r0_3
# 15| r0_5(glval<int>) = FieldAddress[x] : r0_3
# 15| r0_6(int) = Constant[0] :
# 15| mu0_7(int) = Store : r0_5, r0_6
# 16| r0_8(glval<S>) = VariableAddress[s] :
# 16| r0_9(glval<unknown>) = FunctionAddress[MemberFunction] :
# 16| r0_10(int) = Constant[1] :
# 16| r0_11(int) = Call : r0_9, this:r0_8, r0_10
# 16| m0_12(unknown) = ^CallSideEffect : m0_1
# 16| m0_13(unknown) = Chi : m0_1, m0_12
# 17| v0_14(void) = NoOp :
# 14| v0_15(void) = ReturnVoid :
# 14| v0_16(void) = UnmodeledUse : mu*
# 14| v0_17(void) = ExitFunction :
# 14| v0_0(void) = EnterFunction :
# 14| m0_1(unknown) = AliasedDefinition :
# 14| mu0_2(unknown) = UnmodeledDefinition :
# 15| r0_3(glval<S>) = VariableAddress[s] :
# 15| m0_4(S) = Uninitialized : r0_3
# 15| m0_5(unknown) = Chi : m0_1, m0_4
# 15| r0_6(glval<int>) = FieldAddress[x] : r0_3
# 15| r0_7(int) = Constant[0] :
# 15| m0_8(int) = Store : r0_6, r0_7
# 15| m0_9(unknown) = Chi : m0_5, m0_8
# 16| r0_10(glval<S>) = VariableAddress[s] :
# 16| r0_11(glval<unknown>) = FunctionAddress[MemberFunction] :
# 16| r0_12(int) = Constant[1] :
# 16| r0_13(int) = Call : r0_11, this:r0_10, r0_12
# 16| m0_14(unknown) = ^CallSideEffect : m0_9
# 16| m0_15(unknown) = Chi : m0_9, m0_14
# 17| v0_16(void) = NoOp :
# 14| v0_17(void) = ReturnVoid :
# 14| v0_18(void) = UnmodeledUse : mu*
# 14| v0_19(void) = ExitFunction :
# 22| Bad::Point::Point() -> void
# 22| Block 0
@@ -2175,13 +2177,15 @@ ir.cpp:
# 486| r0_3(glval<bool>) = VariableAddress[a] :
# 486| m0_4(bool) = InitializeParameter[a] : r0_3
# 487| r0_5(glval<int>) = VariableAddress[x] :
# 487| mu0_6(int) = Uninitialized : r0_5
# 488| r0_7(glval<int>) = VariableAddress[y] :
# 488| mu0_8(int) = Uninitialized : r0_7
# 489| r0_9(int) = Constant[5] :
# 489| r0_10(glval<bool>) = VariableAddress[a] :
# 489| r0_11(bool) = Load : r0_10, m0_4
# 489| v0_12(void) = ConditionalBranch : r0_11
# 487| m0_6(int) = Uninitialized : r0_5
# 487| m0_7(unknown) = Chi : m0_1, m0_6
# 488| r0_8(glval<int>) = VariableAddress[y] :
# 488| m0_9(int) = Uninitialized : r0_8
# 488| m0_10(unknown) = Chi : m0_7, m0_9
# 489| r0_11(int) = Constant[5] :
# 489| r0_12(glval<bool>) = VariableAddress[a] :
# 489| r0_13(bool) = Load : r0_12, m0_4
# 489| v0_14(void) = ConditionalBranch : r0_13
#-----| False -> Block 3
#-----| True -> Block 2
@@ -2189,8 +2193,8 @@ ir.cpp:
# 489| m1_0(int) = Phi : from 2:m2_2, from 3:m3_2
# 489| r1_1(glval<int>) = VariableAddress[#temp489:6] :
# 489| r1_2(glval<int>) = Load : r1_1, m1_0
# 489| m1_3(int) = Store : r1_2, r0_9
# 489| m1_4(unknown) = Chi : m0_1, m1_3
# 489| m1_3(int) = Store : r1_2, r0_11
# 489| m1_4(unknown) = Chi : m0_10, m1_3
# 490| v1_5(void) = NoOp :
# 486| v1_6(void) = ReturnVoid :
# 486| v1_7(void) = UnmodeledUse : mu*
@@ -2417,49 +2421,52 @@ ir.cpp:
# 519| r0_5(glval<float>) = VariableAddress[f] :
# 519| m0_6(float) = InitializeParameter[f] : r0_5
# 520| r0_7(glval<int[3]>) = VariableAddress[a1] :
# 520| mu0_8(int[3]) = Uninitialized : r0_7
# 520| r0_9(int) = Constant[0] :
# 520| r0_10(glval<int>) = PointerAdd : r0_7, r0_9
# 520| r0_11(unknown[12]) = Constant[0] :
# 520| m0_12(unknown[12]) = Store : r0_10, r0_11
# 520| m0_13(unknown) = Chi : m0_1, m0_12
# 521| r0_14(glval<int[3]>) = VariableAddress[a2] :
# 521| mu0_15(int[3]) = Uninitialized : r0_14
# 521| r0_16(int) = Constant[0] :
# 521| r0_17(glval<int>) = PointerAdd : r0_14, r0_16
# 521| r0_18(glval<int>) = VariableAddress[x] :
# 521| r0_19(int) = Load : r0_18, m0_4
# 521| m0_20(int) = Store : r0_17, r0_19
# 521| m0_21(unknown) = Chi : m0_13, m0_20
# 521| r0_22(int) = Constant[1] :
# 521| r0_23(glval<int>) = PointerAdd : r0_14, r0_22
# 521| r0_24(glval<float>) = VariableAddress[f] :
# 521| r0_25(float) = Load : r0_24, m0_6
# 521| r0_26(int) = Convert : r0_25
# 521| m0_27(int) = Store : r0_23, r0_26
# 521| m0_28(unknown) = Chi : m0_21, m0_27
# 521| r0_29(int) = Constant[2] :
# 521| r0_30(glval<int>) = PointerAdd : r0_14, r0_29
# 521| r0_31(int) = Constant[0] :
# 521| m0_32(int) = Store : r0_30, r0_31
# 521| m0_33(unknown) = Chi : m0_28, m0_32
# 522| r0_34(glval<int[3]>) = VariableAddress[a3] :
# 522| mu0_35(int[3]) = Uninitialized : r0_34
# 522| r0_36(int) = Constant[0] :
# 522| r0_37(glval<int>) = PointerAdd : r0_34, r0_36
# 522| r0_38(glval<int>) = VariableAddress[x] :
# 522| r0_39(int) = Load : r0_38, m0_4
# 522| m0_40(int) = Store : r0_37, r0_39
# 522| m0_41(unknown) = Chi : m0_33, m0_40
# 522| r0_42(int) = Constant[1] :
# 522| r0_43(glval<int>) = PointerAdd : r0_34, r0_42
# 522| r0_44(unknown[8]) = Constant[0] :
# 522| m0_45(unknown[8]) = Store : r0_43, r0_44
# 522| m0_46(unknown) = Chi : m0_41, m0_45
# 523| v0_47(void) = NoOp :
# 519| v0_48(void) = ReturnVoid :
# 519| v0_49(void) = UnmodeledUse : mu*
# 519| v0_50(void) = ExitFunction :
# 520| m0_8(int[3]) = Uninitialized : r0_7
# 520| m0_9(unknown) = Chi : m0_1, m0_8
# 520| r0_10(int) = Constant[0] :
# 520| r0_11(glval<int>) = PointerAdd : r0_7, r0_10
# 520| r0_12(unknown[12]) = Constant[0] :
# 520| m0_13(unknown[12]) = Store : r0_11, r0_12
# 520| m0_14(unknown) = Chi : m0_9, m0_13
# 521| r0_15(glval<int[3]>) = VariableAddress[a2] :
# 521| m0_16(int[3]) = Uninitialized : r0_15
# 521| m0_17(unknown) = Chi : m0_14, m0_16
# 521| r0_18(int) = Constant[0] :
# 521| r0_19(glval<int>) = PointerAdd : r0_15, r0_18
# 521| r0_20(glval<int>) = VariableAddress[x] :
# 521| r0_21(int) = Load : r0_20, m0_4
# 521| m0_22(int) = Store : r0_19, r0_21
# 521| m0_23(unknown) = Chi : m0_17, m0_22
# 521| r0_24(int) = Constant[1] :
# 521| r0_25(glval<int>) = PointerAdd : r0_15, r0_24
# 521| r0_26(glval<float>) = VariableAddress[f] :
# 521| r0_27(float) = Load : r0_26, m0_6
# 521| r0_28(int) = Convert : r0_27
# 521| m0_29(int) = Store : r0_25, r0_28
# 521| m0_30(unknown) = Chi : m0_23, m0_29
# 521| r0_31(int) = Constant[2] :
# 521| r0_32(glval<int>) = PointerAdd : r0_15, r0_31
# 521| r0_33(int) = Constant[0] :
# 521| m0_34(int) = Store : r0_32, r0_33
# 521| m0_35(unknown) = Chi : m0_30, m0_34
# 522| r0_36(glval<int[3]>) = VariableAddress[a3] :
# 522| m0_37(int[3]) = Uninitialized : r0_36
# 522| m0_38(unknown) = Chi : m0_35, m0_37
# 522| r0_39(int) = Constant[0] :
# 522| r0_40(glval<int>) = PointerAdd : r0_36, r0_39
# 522| r0_41(glval<int>) = VariableAddress[x] :
# 522| r0_42(int) = Load : r0_41, m0_4
# 522| m0_43(int) = Store : r0_40, r0_42
# 522| m0_44(unknown) = Chi : m0_38, m0_43
# 522| r0_45(int) = Constant[1] :
# 522| r0_46(glval<int>) = PointerAdd : r0_36, r0_45
# 522| r0_47(unknown[8]) = Constant[0] :
# 522| m0_48(unknown[8]) = Store : r0_46, r0_47
# 522| m0_49(unknown) = Chi : m0_44, m0_48
# 523| v0_50(void) = NoOp :
# 519| v0_51(void) = ReturnVoid :
# 519| v0_52(void) = UnmodeledUse : mu*
# 519| v0_53(void) = ExitFunction :
# 530| UnionInit(int, float) -> void
# 530| Block 0
@@ -2630,69 +2637,74 @@ ir.cpp:
# 572| r0_3(glval<char[32]>) = VariableAddress[a_pad] :
# 572| r0_4(glval<char[1]>) = StringConstant[""] :
# 572| r0_5(char[1]) = Load : r0_4, m0_1
# 572| mu0_6(char[1]) = Store : r0_3, r0_5
# 572| r0_7(unknown[31]) = Constant[0] :
# 572| r0_8(int) = Constant[1] :
# 572| r0_9(glval<char>) = PointerAdd : r0_3, r0_8
# 572| m0_10(unknown[31]) = Store : r0_9, r0_7
# 572| m0_11(unknown) = Chi : m0_1, m0_10
# 573| r0_12(glval<char[4]>) = VariableAddress[a_nopad] :
# 573| r0_13(glval<char[4]>) = StringConstant["foo"] :
# 573| r0_14(char[4]) = Load : r0_13, m0_11
# 573| m0_15(char[4]) = Store : r0_12, r0_14
# 574| r0_16(glval<char[]>) = VariableAddress[a_infer] :
# 574| r0_17(glval<char[5]>) = StringConstant["blah"] :
# 574| r0_18(char[5]) = Load : r0_17, m0_11
# 574| m0_19(char[5]) = Store : r0_16, r0_18
# 575| r0_20(glval<char[2]>) = VariableAddress[b] :
# 575| m0_21(char[2]) = Uninitialized : r0_20
# 576| r0_22(glval<char[2]>) = VariableAddress[c] :
# 576| mu0_23(char[2]) = Uninitialized : r0_22
# 576| r0_24(int) = Constant[0] :
# 576| r0_25(glval<char>) = PointerAdd : r0_22, r0_24
# 576| r0_26(unknown[2]) = Constant[0] :
# 576| m0_27(unknown[2]) = Store : r0_25, r0_26
# 576| m0_28(unknown) = Chi : m0_11, m0_27
# 577| r0_29(glval<char[2]>) = VariableAddress[d] :
# 577| mu0_30(char[2]) = Uninitialized : r0_29
# 577| r0_31(int) = Constant[0] :
# 577| r0_32(glval<char>) = PointerAdd : r0_29, r0_31
# 577| r0_33(char) = Constant[0] :
# 577| m0_34(char) = Store : r0_32, r0_33
# 577| m0_35(unknown) = Chi : m0_28, m0_34
# 577| r0_36(int) = Constant[1] :
# 577| r0_37(glval<char>) = PointerAdd : r0_29, r0_36
# 577| r0_38(char) = Constant[0] :
# 577| m0_39(char) = Store : r0_37, r0_38
# 577| m0_40(unknown) = Chi : m0_35, m0_39
# 578| r0_41(glval<char[2]>) = VariableAddress[e] :
# 578| mu0_42(char[2]) = Uninitialized : r0_41
# 578| r0_43(int) = Constant[0] :
# 578| r0_44(glval<char>) = PointerAdd : r0_41, r0_43
# 578| r0_45(char) = Constant[0] :
# 578| m0_46(char) = Store : r0_44, r0_45
# 578| m0_47(unknown) = Chi : m0_40, m0_46
# 578| r0_48(int) = Constant[1] :
# 578| r0_49(glval<char>) = PointerAdd : r0_41, r0_48
# 578| r0_50(char) = Constant[1] :
# 578| m0_51(char) = Store : r0_49, r0_50
# 578| m0_52(unknown) = Chi : m0_47, m0_51
# 579| r0_53(glval<char[3]>) = VariableAddress[f] :
# 579| mu0_54(char[3]) = Uninitialized : r0_53
# 579| r0_55(int) = Constant[0] :
# 579| r0_56(glval<char>) = PointerAdd : r0_53, r0_55
# 579| r0_57(char) = Constant[0] :
# 579| m0_58(char) = Store : r0_56, r0_57
# 579| m0_59(unknown) = Chi : m0_52, m0_58
# 579| r0_60(int) = Constant[1] :
# 579| r0_61(glval<char>) = PointerAdd : r0_53, r0_60
# 579| r0_62(unknown[2]) = Constant[0] :
# 579| m0_63(unknown[2]) = Store : r0_61, r0_62
# 572| m0_6(char[1]) = Store : r0_3, r0_5
# 572| m0_7(unknown) = Chi : m0_1, m0_6
# 572| r0_8(unknown[31]) = Constant[0] :
# 572| r0_9(int) = Constant[1] :
# 572| r0_10(glval<char>) = PointerAdd : r0_3, r0_9
# 572| m0_11(unknown[31]) = Store : r0_10, r0_8
# 572| m0_12(unknown) = Chi : m0_7, m0_11
# 573| r0_13(glval<char[4]>) = VariableAddress[a_nopad] :
# 573| r0_14(glval<char[4]>) = StringConstant["foo"] :
# 573| r0_15(char[4]) = Load : r0_14, m0_12
# 573| m0_16(char[4]) = Store : r0_13, r0_15
# 574| r0_17(glval<char[]>) = VariableAddress[a_infer] :
# 574| r0_18(glval<char[5]>) = StringConstant["blah"] :
# 574| r0_19(char[5]) = Load : r0_18, m0_12
# 574| m0_20(char[5]) = Store : r0_17, r0_19
# 575| r0_21(glval<char[2]>) = VariableAddress[b] :
# 575| m0_22(char[2]) = Uninitialized : r0_21
# 576| r0_23(glval<char[2]>) = VariableAddress[c] :
# 576| m0_24(char[2]) = Uninitialized : r0_23
# 576| m0_25(unknown) = Chi : m0_12, m0_24
# 576| r0_26(int) = Constant[0] :
# 576| r0_27(glval<char>) = PointerAdd : r0_23, r0_26
# 576| r0_28(unknown[2]) = Constant[0] :
# 576| m0_29(unknown[2]) = Store : r0_27, r0_28
# 576| m0_30(unknown) = Chi : m0_25, m0_29
# 577| r0_31(glval<char[2]>) = VariableAddress[d] :
# 577| m0_32(char[2]) = Uninitialized : r0_31
# 577| m0_33(unknown) = Chi : m0_30, m0_32
# 577| r0_34(int) = Constant[0] :
# 577| r0_35(glval<char>) = PointerAdd : r0_31, r0_34
# 577| r0_36(char) = Constant[0] :
# 577| m0_37(char) = Store : r0_35, r0_36
# 577| m0_38(unknown) = Chi : m0_33, m0_37
# 577| r0_39(int) = Constant[1] :
# 577| r0_40(glval<char>) = PointerAdd : r0_31, r0_39
# 577| r0_41(char) = Constant[0] :
# 577| m0_42(char) = Store : r0_40, r0_41
# 577| m0_43(unknown) = Chi : m0_38, m0_42
# 578| r0_44(glval<char[2]>) = VariableAddress[e] :
# 578| m0_45(char[2]) = Uninitialized : r0_44
# 578| m0_46(unknown) = Chi : m0_43, m0_45
# 578| r0_47(int) = Constant[0] :
# 578| r0_48(glval<char>) = PointerAdd : r0_44, r0_47
# 578| r0_49(char) = Constant[0] :
# 578| m0_50(char) = Store : r0_48, r0_49
# 578| m0_51(unknown) = Chi : m0_46, m0_50
# 578| r0_52(int) = Constant[1] :
# 578| r0_53(glval<char>) = PointerAdd : r0_44, r0_52
# 578| r0_54(char) = Constant[1] :
# 578| m0_55(char) = Store : r0_53, r0_54
# 578| m0_56(unknown) = Chi : m0_51, m0_55
# 579| r0_57(glval<char[3]>) = VariableAddress[f] :
# 579| m0_58(char[3]) = Uninitialized : r0_57
# 579| m0_59(unknown) = Chi : m0_56, m0_58
# 579| r0_60(int) = Constant[0] :
# 579| r0_61(glval<char>) = PointerAdd : r0_57, r0_60
# 579| r0_62(char) = Constant[0] :
# 579| m0_63(char) = Store : r0_61, r0_62
# 579| m0_64(unknown) = Chi : m0_59, m0_63
# 580| v0_65(void) = NoOp :
# 571| v0_66(void) = ReturnVoid :
# 571| v0_67(void) = UnmodeledUse : mu*
# 571| v0_68(void) = ExitFunction :
# 579| r0_65(int) = Constant[1] :
# 579| r0_66(glval<char>) = PointerAdd : r0_57, r0_65
# 579| r0_67(unknown[2]) = Constant[0] :
# 579| m0_68(unknown[2]) = Store : r0_66, r0_67
# 579| m0_69(unknown) = Chi : m0_64, m0_68
# 580| v0_70(void) = NoOp :
# 571| v0_71(void) = ReturnVoid :
# 571| v0_72(void) = UnmodeledUse : mu*
# 571| v0_73(void) = ExitFunction :
# 584| VarArgs() -> void
# 584| Block 0
@@ -2780,31 +2792,32 @@ ir.cpp:
# 622| r0_5(glval<String *>) = VariableAddress[p] :
# 622| m0_6(String *) = InitializeParameter[p] : r0_5
# 622| r0_7(glval<String>) = VariableAddress[s] :
# 622| mu0_8(String) = InitializeParameter[s] : r0_7
# 623| r0_9(glval<String &>) = VariableAddress[r] :
# 623| r0_10(String &) = Load : r0_9, m0_4
# 623| r0_11(glval<String>) = Convert : r0_10
# 623| r0_12(glval<unknown>) = FunctionAddress[c_str] :
# 623| r0_13(char *) = Call : r0_12, this:r0_11
# 623| m0_14(unknown) = ^CallSideEffect : m0_1
# 623| m0_15(unknown) = Chi : m0_1, m0_14
# 624| r0_16(glval<String *>) = VariableAddress[p] :
# 624| r0_17(String *) = Load : r0_16, m0_6
# 624| r0_18(String *) = Convert : r0_17
# 624| r0_19(glval<unknown>) = FunctionAddress[c_str] :
# 624| r0_20(char *) = Call : r0_19, this:r0_18
# 624| m0_21(unknown) = ^CallSideEffect : m0_15
# 624| m0_22(unknown) = Chi : m0_15, m0_21
# 625| r0_23(glval<String>) = VariableAddress[s] :
# 625| r0_24(glval<String>) = Convert : r0_23
# 625| r0_25(glval<unknown>) = FunctionAddress[c_str] :
# 625| r0_26(char *) = Call : r0_25, this:r0_24
# 625| m0_27(unknown) = ^CallSideEffect : m0_22
# 625| m0_28(unknown) = Chi : m0_22, m0_27
# 626| v0_29(void) = NoOp :
# 622| v0_30(void) = ReturnVoid :
# 622| v0_31(void) = UnmodeledUse : mu*
# 622| v0_32(void) = ExitFunction :
# 622| m0_8(String) = InitializeParameter[s] : r0_7
# 622| m0_9(unknown) = Chi : m0_1, m0_8
# 623| r0_10(glval<String &>) = VariableAddress[r] :
# 623| r0_11(String &) = Load : r0_10, m0_4
# 623| r0_12(glval<String>) = Convert : r0_11
# 623| r0_13(glval<unknown>) = FunctionAddress[c_str] :
# 623| r0_14(char *) = Call : r0_13, this:r0_12
# 623| m0_15(unknown) = ^CallSideEffect : m0_9
# 623| m0_16(unknown) = Chi : m0_9, m0_15
# 624| r0_17(glval<String *>) = VariableAddress[p] :
# 624| r0_18(String *) = Load : r0_17, m0_6
# 624| r0_19(String *) = Convert : r0_18
# 624| r0_20(glval<unknown>) = FunctionAddress[c_str] :
# 624| r0_21(char *) = Call : r0_20, this:r0_19
# 624| m0_22(unknown) = ^CallSideEffect : m0_16
# 624| m0_23(unknown) = Chi : m0_16, m0_22
# 625| r0_24(glval<String>) = VariableAddress[s] :
# 625| r0_25(glval<String>) = Convert : r0_24
# 625| r0_26(glval<unknown>) = FunctionAddress[c_str] :
# 625| r0_27(char *) = Call : r0_26, this:r0_25
# 625| m0_28(unknown) = ^CallSideEffect : m0_23
# 625| m0_29(unknown) = Chi : m0_23, m0_28
# 626| v0_30(void) = NoOp :
# 622| v0_31(void) = ReturnVoid :
# 622| v0_32(void) = UnmodeledUse : mu*
# 622| v0_33(void) = ExitFunction :
# 630| C::StaticMemberFunction(int) -> int
# 630| Block 0
@@ -4071,43 +4084,46 @@ ir.cpp:
# 888| m0_1(unknown) = AliasedDefinition :
# 888| mu0_2(unknown) = UnmodeledDefinition :
# 888| r0_3(glval<int>) = VariableAddress[x] :
# 888| mu0_4(int) = InitializeParameter[x] : r0_3
# 889| r0_5(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 889| mu0_6(__va_list_tag[1]) = Uninitialized : r0_5
# 891| r0_7(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 891| r0_8(__va_list_tag *) = Convert : r0_7
# 891| r0_9(glval<int>) = VariableAddress[x] :
# 891| v0_10(void) = VarArgsStart : r0_8, r0_9
# 892| r0_11(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 892| mu0_12(__va_list_tag[1]) = Uninitialized : r0_11
# 893| r0_13(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 893| r0_14(__va_list_tag *) = Convert : r0_13
# 893| r0_15(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 893| r0_16(__va_list_tag *) = Convert : r0_15
# 893| v0_17(void) = VarArgsStart : r0_14, r0_16
# 894| r0_18(glval<double>) = VariableAddress[d] :
# 894| r0_19(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 894| r0_20(__va_list_tag *) = Convert : r0_19
# 894| r0_21(glval<double>) = VarArg : r0_20
# 894| r0_22(double) = Load : r0_21, m0_1
# 894| m0_23(double) = Store : r0_18, r0_22
# 895| r0_24(glval<float>) = VariableAddress[f] :
# 895| r0_25(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 895| r0_26(__va_list_tag *) = Convert : r0_25
# 895| r0_27(glval<double>) = VarArg : r0_26
# 895| r0_28(double) = Load : r0_27, m0_1
# 895| r0_29(float) = Convert : r0_28
# 895| m0_30(float) = Store : r0_24, r0_29
# 896| r0_31(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 896| r0_32(__va_list_tag *) = Convert : r0_31
# 896| v0_33(void) = VarArgsEnd : r0_32
# 897| r0_34(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 897| r0_35(__va_list_tag *) = Convert : r0_34
# 897| v0_36(void) = VarArgsEnd : r0_35
# 898| v0_37(void) = NoOp :
# 888| v0_38(void) = ReturnVoid :
# 888| v0_39(void) = UnmodeledUse : mu*
# 888| v0_40(void) = ExitFunction :
# 888| m0_4(int) = InitializeParameter[x] : r0_3
# 888| m0_5(unknown) = Chi : m0_1, m0_4
# 889| r0_6(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 889| m0_7(__va_list_tag[1]) = Uninitialized : r0_6
# 889| m0_8(unknown) = Chi : m0_5, m0_7
# 891| r0_9(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 891| r0_10(__va_list_tag *) = Convert : r0_9
# 891| r0_11(glval<int>) = VariableAddress[x] :
# 891| v0_12(void) = VarArgsStart : r0_10, r0_11
# 892| r0_13(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 892| m0_14(__va_list_tag[1]) = Uninitialized : r0_13
# 892| m0_15(unknown) = Chi : m0_8, m0_14
# 893| r0_16(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 893| r0_17(__va_list_tag *) = Convert : r0_16
# 893| r0_18(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 893| r0_19(__va_list_tag *) = Convert : r0_18
# 893| v0_20(void) = VarArgsStart : r0_17, r0_19
# 894| r0_21(glval<double>) = VariableAddress[d] :
# 894| r0_22(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 894| r0_23(__va_list_tag *) = Convert : r0_22
# 894| r0_24(glval<double>) = VarArg : r0_23
# 894| r0_25(double) = Load : r0_24, m0_15
# 894| m0_26(double) = Store : r0_21, r0_25
# 895| r0_27(glval<float>) = VariableAddress[f] :
# 895| r0_28(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 895| r0_29(__va_list_tag *) = Convert : r0_28
# 895| r0_30(glval<double>) = VarArg : r0_29
# 895| r0_31(double) = Load : r0_30, m0_15
# 895| r0_32(float) = Convert : r0_31
# 895| m0_33(float) = Store : r0_27, r0_32
# 896| r0_34(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 896| r0_35(__va_list_tag *) = Convert : r0_34
# 896| v0_36(void) = VarArgsEnd : r0_35
# 897| r0_37(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 897| r0_38(__va_list_tag *) = Convert : r0_37
# 897| v0_39(void) = VarArgsEnd : r0_38
# 898| v0_40(void) = NoOp :
# 888| v0_41(void) = ReturnVoid :
# 888| v0_42(void) = UnmodeledUse : mu*
# 888| v0_43(void) = ExitFunction :
# 900| CastToVoid(int) -> void
# 900| Block 0
@@ -4115,13 +4131,14 @@ ir.cpp:
# 900| m0_1(unknown) = AliasedDefinition :
# 900| mu0_2(unknown) = UnmodeledDefinition :
# 900| r0_3(glval<int>) = VariableAddress[x] :
# 900| mu0_4(int) = InitializeParameter[x] : r0_3
# 901| r0_5(glval<int>) = VariableAddress[x] :
# 901| v0_6(void) = Convert : r0_5
# 902| v0_7(void) = NoOp :
# 900| v0_8(void) = ReturnVoid :
# 900| v0_9(void) = UnmodeledUse : mu*
# 900| v0_10(void) = ExitFunction :
# 900| m0_4(int) = InitializeParameter[x] : r0_3
# 900| m0_5(unknown) = Chi : m0_1, m0_4
# 901| r0_6(glval<int>) = VariableAddress[x] :
# 901| v0_7(void) = Convert : r0_6
# 902| v0_8(void) = NoOp :
# 900| v0_9(void) = ReturnVoid :
# 900| v0_10(void) = UnmodeledUse : mu*
# 900| v0_11(void) = ExitFunction :
# 904| ConstantConditions(int) -> void
# 904| Block 0
@@ -4330,43 +4347,44 @@ ir.cpp:
# 961| m0_1(unknown) = AliasedDefinition :
# 961| mu0_2(unknown) = UnmodeledDefinition :
# 962| r0_3(glval<int[1000]>) = VariableAddress[a1] :
# 962| mu0_4(int[1000]) = Uninitialized : r0_3
# 962| r0_5(int) = Constant[0] :
# 962| r0_6(glval<int>) = PointerAdd : r0_3, r0_5
# 962| r0_7(unknown[8]) = Constant[0] :
# 962| m0_8(unknown[8]) = Store : r0_6, r0_7
# 962| m0_9(unknown) = Chi : m0_1, m0_8
# 962| r0_10(int) = Constant[2] :
# 962| r0_11(glval<int>) = PointerAdd : r0_3, r0_10
# 962| r0_12(int) = Constant[10002] :
# 962| m0_13(int) = Store : r0_11, r0_12
# 962| m0_14(unknown) = Chi : m0_9, m0_13
# 962| r0_15(int) = Constant[3] :
# 962| r0_16(glval<int>) = PointerAdd : r0_3, r0_15
# 962| r0_17(unknown[3588]) = Constant[0] :
# 962| m0_18(unknown[3588]) = Store : r0_16, r0_17
# 962| m0_19(unknown) = Chi : m0_14, m0_18
# 962| r0_20(int) = Constant[900] :
# 962| r0_21(glval<int>) = PointerAdd : r0_3, r0_20
# 962| r0_22(int) = Constant[10900] :
# 962| m0_23(int) = Store : r0_21, r0_22
# 962| m0_24(unknown) = Chi : m0_19, m0_23
# 962| r0_25(int) = Constant[901] :
# 962| r0_26(glval<int>) = PointerAdd : r0_3, r0_25
# 962| r0_27(unknown[396]) = Constant[0] :
# 962| m0_28(unknown[396]) = Store : r0_26, r0_27
# 962| m0_29(unknown) = Chi : m0_24, m0_28
# 963| r0_30(glval<int>) = VariableAddress[#return] :
# 963| r0_31(glval<int[1000]>) = VariableAddress[a1] :
# 963| r0_32(int *) = Convert : r0_31
# 963| r0_33(int) = Constant[900] :
# 963| r0_34(int *) = PointerAdd[4] : r0_32, r0_33
# 963| r0_35(int) = Load : r0_34, mu0_2
# 963| m0_36(int) = Store : r0_30, r0_35
# 961| r0_37(glval<int>) = VariableAddress[#return] :
# 961| v0_38(void) = ReturnValue : r0_37, m0_36
# 961| v0_39(void) = UnmodeledUse : mu*
# 961| v0_40(void) = ExitFunction :
# 962| m0_4(int[1000]) = Uninitialized : r0_3
# 962| m0_5(unknown) = Chi : m0_1, m0_4
# 962| r0_6(int) = Constant[0] :
# 962| r0_7(glval<int>) = PointerAdd : r0_3, r0_6
# 962| r0_8(unknown[8]) = Constant[0] :
# 962| m0_9(unknown[8]) = Store : r0_7, r0_8
# 962| m0_10(unknown) = Chi : m0_5, m0_9
# 962| r0_11(int) = Constant[2] :
# 962| r0_12(glval<int>) = PointerAdd : r0_3, r0_11
# 962| r0_13(int) = Constant[10002] :
# 962| m0_14(int) = Store : r0_12, r0_13
# 962| m0_15(unknown) = Chi : m0_10, m0_14
# 962| r0_16(int) = Constant[3] :
# 962| r0_17(glval<int>) = PointerAdd : r0_3, r0_16
# 962| r0_18(unknown[3588]) = Constant[0] :
# 962| m0_19(unknown[3588]) = Store : r0_17, r0_18
# 962| m0_20(unknown) = Chi : m0_15, m0_19
# 962| r0_21(int) = Constant[900] :
# 962| r0_22(glval<int>) = PointerAdd : r0_3, r0_21
# 962| r0_23(int) = Constant[10900] :
# 962| m0_24(int) = Store : r0_22, r0_23
# 962| m0_25(unknown) = Chi : m0_20, m0_24
# 962| r0_26(int) = Constant[901] :
# 962| r0_27(glval<int>) = PointerAdd : r0_3, r0_26
# 962| r0_28(unknown[396]) = Constant[0] :
# 962| m0_29(unknown[396]) = Store : r0_27, r0_28
# 962| m0_30(unknown) = Chi : m0_25, m0_29
# 963| r0_31(glval<int>) = VariableAddress[#return] :
# 963| r0_32(glval<int[1000]>) = VariableAddress[a1] :
# 963| r0_33(int *) = Convert : r0_32
# 963| r0_34(int) = Constant[900] :
# 963| r0_35(int *) = PointerAdd[4] : r0_33, r0_34
# 963| r0_36(int) = Load : r0_35, mu0_2
# 963| m0_37(int) = Store : r0_31, r0_36
# 961| r0_38(glval<int>) = VariableAddress[#return] :
# 961| v0_39(void) = ReturnValue : r0_38, m0_37
# 961| v0_40(void) = UnmodeledUse : mu*
# 961| v0_41(void) = ExitFunction :
# 966| IfStmtWithDeclaration(int, int) -> void
# 966| Block 0