Merge pull request #5909 from tamasvajk/fix/foreach-ir-temp-var

C#: Fix type of temp foreach variable in IR
This commit is contained in:
Tamás Vajk
2021-05-21 17:24:08 +02:00
committed by GitHub
5 changed files with 59 additions and 38 deletions

View File

@@ -182,15 +182,21 @@ abstract class TranslatedCompilerGeneratedVariableAccess extends TranslatedCompi
override Instruction getChildSuccessor(TranslatedElement child) { none() }
/**
* Returns the type of the accessed variable. Can be overriden when the return
* type is different than the type of the underlying variable.
*/
Type getVariableType() { result = getResultType() }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CSharpType resultType) {
tag = AddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = getTypeForGLValue(getResultType())
resultType = getTypeForGLValue(getVariableType())
or
needsLoad() and
tag = LoadTag() and
opcode instanceof Opcode::Load and
resultType = getTypeForPRValue(getResultType())
resultType = getTypeForPRValue(getVariableType())
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {

View File

@@ -359,9 +359,16 @@ private class TranslatedMoveNextEnumAcc extends TTranslatedCompilerGeneratedElem
override Type getResultType() { result instanceof BoolType }
override Type getVariableType() {
exists(TranslatedForeachGetEnumerator ge |
ge.getAST() = generatedBy and
result = ge.getCallResultType()
)
}
override predicate hasTempVariable(TempVariableTag tag, CSharpType type) {
tag = ForeachEnumTempVar() and
type = getTypeForPRValue(getResultType())
type = getTypeForPRValue(getVariableType())
}
override IRVariable getInstructionVariable(InstructionTag tag) {
@@ -384,9 +391,16 @@ private class TranslatedForeachCurrentEnumAcc extends TTranslatedCompilerGenerat
override Type getResultType() { result instanceof BoolType }
override Type getVariableType() {
exists(TranslatedForeachGetEnumerator ge |
ge.getAST() = generatedBy and
result = ge.getCallResultType()
)
}
override predicate hasTempVariable(TempVariableTag tag, CSharpType type) {
tag = ForeachEnumTempVar() and
type = getTypeForPRValue(getResultType())
type = getTypeForPRValue(getVariableType())
}
override IRVariable getInstructionVariable(InstructionTag tag) {
@@ -409,9 +423,16 @@ private class TranslatedForeachDisposeEnumAcc extends TTranslatedCompilerGenerat
override Type getResultType() { result instanceof BoolType }
override Type getVariableType() {
exists(TranslatedForeachGetEnumerator ge |
ge.getAST() = generatedBy and
result = ge.getCallResultType()
)
}
override predicate hasTempVariable(TempVariableTag tag, CSharpType type) {
tag = ForeachEnumTempVar() and
type = getTypeForPRValue(getResultType())
type = getTypeForPRValue(getVariableType())
}
override IRVariable getInstructionVariable(InstructionTag tag) {

View File

@@ -613,48 +613,48 @@ foreach.cs:
# 5| r5_28(glval<Int32>) = PointerAdd[4] : r5_1, r5_27
# 5| r5_29(Int32) = Constant[7] :
# 5| mu5_30(Int32) = Store[?] : &:r5_28, r5_29
# 7| r7_1(glval<Boolean>) = VariableAddress[#temp7:9] :
# 7| r7_1(glval<IEnumerator>) = VariableAddress[#temp7:9] :
# 7| r7_2(glval<Int32[]>) = VariableAddress[a_array] :
# 7| r7_3(Int32[]) = Load[a_array] : &:r7_2, ~m?
# 7| r7_4(<funcaddr>) = FunctionAddress[GetEnumerator] :
# 7| r7_5(IEnumerator) = Call[GetEnumerator] : func:r7_4, this:r7_3
# 7| mu7_6(<unknown>) = ^CallSideEffect : ~m?
# 7| mu7_7(Boolean) = Store[#temp7:9] : &:r7_1, r7_5
# 7| mu7_7(IEnumerator) = Store[#temp7:9] : &:r7_1, r7_5
#-----| Goto -> Block 1
# 7| Block 1
# 7| r7_8(glval<Boolean>) = VariableAddress[#temp7:9] :
# 7| r7_9(Boolean) = Load[#temp7:9] : &:r7_8, ~m?
# 7| r7_10(<funcaddr>) = FunctionAddress[MoveNext] :
# 7| r7_11(Boolean) = Call[MoveNext] : func:r7_10, this:r7_9
# 7| mu7_12(<unknown>) = ^CallSideEffect : ~m?
# 7| v7_13(Void) = ConditionalBranch : r7_11
# 7| r7_8(glval<IEnumerator>) = VariableAddress[#temp7:9] :
# 7| r7_9(IEnumerator) = Load[#temp7:9] : &:r7_8, ~m?
# 7| r7_10(<funcaddr>) = FunctionAddress[MoveNext] :
# 7| r7_11(Boolean) = Call[MoveNext] : func:r7_10, this:r7_9
# 7| mu7_12(<unknown>) = ^CallSideEffect : ~m?
# 7| v7_13(Void) = ConditionalBranch : r7_11
#-----| False -> Block 3
#-----| True -> Block 2
# 7| Block 2
# 7| r7_14(glval<Int32>) = VariableAddress[items] :
# 7| r7_15(glval<Boolean>) = VariableAddress[#temp7:9] :
# 7| r7_16(Boolean) = Load[#temp7:9] : &:r7_15, ~m?
# 7| r7_17(<funcaddr>) = FunctionAddress[get_Current] :
# 7| r7_18(Int32) = Call[get_Current] : func:r7_17, this:r7_16
# 7| mu7_19(<unknown>) = ^CallSideEffect : ~m?
# 7| mu7_20(Int32) = Store[items] : &:r7_14, r7_18
# 9| r9_1(glval<Int32>) = VariableAddress[x] :
# 9| r9_2(glval<Int32>) = VariableAddress[items] :
# 9| r9_3(Int32) = Load[items] : &:r9_2, ~m?
# 9| mu9_4(Int32) = Store[x] : &:r9_1, r9_3
# 7| r7_14(glval<Int32>) = VariableAddress[items] :
# 7| r7_15(glval<IEnumerator>) = VariableAddress[#temp7:9] :
# 7| r7_16(IEnumerator) = Load[#temp7:9] : &:r7_15, ~m?
# 7| r7_17(<funcaddr>) = FunctionAddress[get_Current] :
# 7| r7_18(Int32) = Call[get_Current] : func:r7_17, this:r7_16
# 7| mu7_19(<unknown>) = ^CallSideEffect : ~m?
# 7| mu7_20(Int32) = Store[items] : &:r7_14, r7_18
# 9| r9_1(glval<Int32>) = VariableAddress[x] :
# 9| r9_2(glval<Int32>) = VariableAddress[items] :
# 9| r9_3(Int32) = Load[items] : &:r9_2, ~m?
# 9| mu9_4(Int32) = Store[x] : &:r9_1, r9_3
#-----| Goto (back edge) -> Block 1
# 7| Block 3
# 7| r7_21(glval<Boolean>) = VariableAddress[#temp7:9] :
# 7| r7_22(Boolean) = Load[#temp7:9] : &:r7_21, ~m?
# 7| r7_23(<funcaddr>) = FunctionAddress[Dispose] :
# 7| v7_24(Void) = Call[Dispose] : func:r7_23, this:r7_22
# 7| mu7_25(<unknown>) = ^CallSideEffect : ~m?
# 4| v4_3(Void) = ReturnVoid :
# 4| v4_4(Void) = AliasedUse : ~m?
# 4| v4_5(Void) = ExitFunction :
# 7| r7_21(glval<IEnumerator>) = VariableAddress[#temp7:9] :
# 7| r7_22(IEnumerator) = Load[#temp7:9] : &:r7_21, ~m?
# 7| r7_23(<funcaddr>) = FunctionAddress[Dispose] :
# 7| v7_24(Void) = Call[Dispose] : func:r7_23, this:r7_22
# 7| mu7_25(<unknown>) = ^CallSideEffect : ~m?
# 4| v4_3(Void) = ReturnVoid :
# 4| v4_4(Void) = AliasedUse : ~m?
# 4| v4_5(Void) = ExitFunction :
func_with_param_call.cs:
# 5| System.Int32 test_call_with_param.f(System.Int32,System.Int32)

View File

@@ -26,9 +26,6 @@ fieldAddressOnNonPointer
| inoutref.cs:19:13:19:17 | FieldAddress: access to field fld | FieldAddress instruction 'FieldAddress: access to field fld' has an object address operand that is not an address, in function '$@'. | inoutref.cs:16:17:16:17 | System.Void InOutRef.F(System.Int32,MyStruct,MyStruct,MyClass,MyClass) | System.Void InOutRef.F(System.Int32,MyStruct,MyStruct,MyClass,MyClass) |
| pointers.cs:35:17:35:24 | FieldAddress: access to field fld | FieldAddress instruction 'FieldAddress: access to field fld' has an object address operand that is not an address, in function '$@'. | pointers.cs:25:17:25:20 | System.Void Pointers.Main() | System.Void Pointers.Main() |
thisArgumentIsNonPointer
| foreach.cs:7:9:10:9 | Call: foreach (... ... in ...) ... | Call instruction 'Call: foreach (... ... in ...) ...' has a `this` argument operand that is not an address, in function '$@'. | foreach.cs:4:24:4:27 | System.Void ForEach.Main() | System.Void ForEach.Main() |
| foreach.cs:7:9:10:9 | Call: foreach (... ... in ...) ... | Call instruction 'Call: foreach (... ... in ...) ...' has a `this` argument operand that is not an address, in function '$@'. | foreach.cs:4:24:4:27 | System.Void ForEach.Main() | System.Void ForEach.Main() |
| foreach.cs:7:9:10:9 | Call: foreach (... ... in ...) ... | Call instruction 'Call: foreach (... ... in ...) ...' has a `this` argument operand that is not an address, in function '$@'. | foreach.cs:4:24:4:27 | System.Void ForEach.Main() | System.Void ForEach.Main() |
| inoutref.cs:32:22:32:35 | Call: object creation of type MyStruct | Call instruction 'Call: object creation of type MyStruct' has a `this` argument operand that is not an address, in function '$@'. | inoutref.cs:29:17:29:20 | System.Void InOutRef.Main() | System.Void InOutRef.Main() |
| pointers.cs:27:22:27:35 | Call: object creation of type MyStruct | Call instruction 'Call: object creation of type MyStruct' has a `this` argument operand that is not an address, in function '$@'. | pointers.cs:25:17:25:20 | System.Void Pointers.Main() | System.Void Pointers.Main() |
missingCanonicalLanguageType

View File

@@ -26,9 +26,6 @@ fieldAddressOnNonPointer
| inoutref.cs:19:13:19:17 | FieldAddress: access to field fld | FieldAddress instruction 'FieldAddress: access to field fld' has an object address operand that is not an address, in function '$@'. | inoutref.cs:16:17:16:17 | System.Void InOutRef.F(System.Int32,MyStruct,MyStruct,MyClass,MyClass) | System.Void InOutRef.F(System.Int32,MyStruct,MyStruct,MyClass,MyClass) |
| pointers.cs:35:17:35:24 | FieldAddress: access to field fld | FieldAddress instruction 'FieldAddress: access to field fld' has an object address operand that is not an address, in function '$@'. | pointers.cs:25:17:25:20 | System.Void Pointers.Main() | System.Void Pointers.Main() |
thisArgumentIsNonPointer
| foreach.cs:7:9:10:9 | Call: foreach (... ... in ...) ... | Call instruction 'Call: foreach (... ... in ...) ...' has a `this` argument operand that is not an address, in function '$@'. | foreach.cs:4:24:4:27 | System.Void ForEach.Main() | System.Void ForEach.Main() |
| foreach.cs:7:9:10:9 | Call: foreach (... ... in ...) ... | Call instruction 'Call: foreach (... ... in ...) ...' has a `this` argument operand that is not an address, in function '$@'. | foreach.cs:4:24:4:27 | System.Void ForEach.Main() | System.Void ForEach.Main() |
| foreach.cs:7:9:10:9 | Call: foreach (... ... in ...) ... | Call instruction 'Call: foreach (... ... in ...) ...' has a `this` argument operand that is not an address, in function '$@'. | foreach.cs:4:24:4:27 | System.Void ForEach.Main() | System.Void ForEach.Main() |
| inoutref.cs:32:22:32:35 | Call: object creation of type MyStruct | Call instruction 'Call: object creation of type MyStruct' has a `this` argument operand that is not an address, in function '$@'. | inoutref.cs:29:17:29:20 | System.Void InOutRef.Main() | System.Void InOutRef.Main() |
| pointers.cs:27:22:27:35 | Call: object creation of type MyStruct | Call instruction 'Call: object creation of type MyStruct' has a `this` argument operand that is not an address, in function '$@'. | pointers.cs:25:17:25:20 | System.Void Pointers.Main() | System.Void Pointers.Main() |
missingCanonicalLanguageType