Skip to content

Commit 795566c

Browse files
committed
yet another fix for the #305
1 parent af6e571 commit 795566c

File tree

2 files changed

+52
-10
lines changed

2 files changed

+52
-10
lines changed

src/FastExpressionCompiler/FastExpressionCompiler.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3339,6 +3339,15 @@ private static bool TryEmitArrayIndex(Type type, ILGenerator il, ParentFlags par
33393339
il.Emit(OpCodes.Ldelem_Ref);
33403340
return true;
33413341
}
3342+
3343+
// access the value type by address when it is used later for the member access or as instance in the method call
3344+
if ((parent & (ParentFlags.MemberAccess | ParentFlags.InstanceAccess)) != 0)
3345+
{
3346+
il.Emit(OpCodes.Ldelema, type);
3347+
closure.LastEmitIsAddress = true;
3348+
return true;
3349+
}
3350+
33423351
if (type == typeof(Int32))
33433352
il.Emit(OpCodes.Ldelem_I4);
33443353
else if (type == typeof(Int64))
@@ -3361,13 +3370,8 @@ private static bool TryEmitArrayIndex(Type type, ILGenerator il, ParentFlags par
33613370
il.Emit(OpCodes.Ldelem_U2);
33623371
else if (type == typeof(UInt32))
33633372
il.Emit(OpCodes.Ldelem_U4);
3364-
else if ((parent & (ParentFlags.MemberAccess | ParentFlags.InstanceAccess)) == 0)
3365-
il.Emit(OpCodes.Ldelem, type);
33663373
else
3367-
{
3368-
il.Emit(OpCodes.Ldelema, type);
3369-
closure.LastEmitIsAddress = true;
3370-
}
3374+
il.Emit(OpCodes.Ldelem, type);
33713375
return true;
33723376
}
33733377

@@ -3966,7 +3970,6 @@ private static bool TryEmitIndexAssign(IndexExpression indexExpr, Type instType,
39663970
il.Emit(OpCodes.Stelem_I);
39673971
else
39683972
il.Emit(OpCodes.Stelem, elementType);
3969-
//todo: UInt64 as there is no OpCodes? Stelem_Ref?
39703973
return true;
39713974
}
39723975

test/FastExpressionCompiler.IssueTests/Issue305_CompileFast_generates_incorrect_code_with_arrays_and_printing.cs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@ public class Issue305_CompileFast_generates_incorrect_code_with_arrays_and_print
1717
{
1818
public int Run()
1919
{
20-
Test1();
21-
return 1;
20+
Test_double_array_index_access();
21+
Test_double_array_index_access_and_instance_call();
22+
return 2;
2223
}
2324

2425
private List<double> _items = new List<double>();
2526

2627
public void WriteLine(double n) => _items.Add(n);
28+
public void WriteLine(int n) => _items.Add(n);
2729

2830
[Test]
29-
public void Test1()
31+
public void Test_double_array_index_access()
3032
{
3133
var arr = Variable(typeof(double[]), "arr");
3234

@@ -60,5 +62,42 @@ public void Test1()
6062
Assert.AreEqual(123.456, res2);
6163
Assert.AreEqual(4, _items.Count(x => x == 123.456));
6264
}
65+
66+
[Test]
67+
public void Test_double_array_index_access_and_instance_call()
68+
{
69+
var arr = Variable(typeof(double[]), "arr");
70+
71+
var print = this.GetType().GetMethod(nameof(WriteLine), new[] { typeof(int) });
72+
var compareTo = typeof(double).GetMethod(nameof(double.CompareTo), new[] { typeof(double) });
73+
74+
var expr = Lambda<Func<double>>(
75+
Block(new[] { arr },
76+
Assign(arr, NewArrayBounds(typeof(double), Constant(1))),
77+
Assign(ArrayAccess(arr, Constant(0)), Constant(123.456)),
78+
79+
Call(Constant(this), print, Call(ArrayAccess(arr, Constant(0)), compareTo, Constant(123.456))),
80+
Call(Constant(this), print, Call(ArrayAccess(arr, Constant(0)), compareTo, Constant(123.456))),
81+
82+
ArrayAccess(arr, Constant(0))
83+
));
84+
85+
expr.PrintCSharp();
86+
87+
_items.Clear();
88+
89+
var fs = expr.CompileSys();
90+
fs.PrintIL();
91+
92+
var res = fs();
93+
Assert.AreEqual(123.456, res);
94+
95+
var ff = expr.CompileFast(true);
96+
ff.PrintIL();
97+
98+
var res2 = ff();
99+
Assert.AreEqual(123.456, res2);
100+
Assert.AreEqual(4, _items.Count(x => x == 0));
101+
}
63102
}
64103
}

0 commit comments

Comments
 (0)