-
-
Notifications
You must be signed in to change notification settings - Fork 92
add the possibility to check the IL in tests #145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Great idea! |
|
||
// Check TryEmitInvertedNullComparison is used | ||
var il = ILReaderFactory.Create(convert1.Method).ToList(); | ||
Assert.AreEqual(il[0].OpCode, OpCodes.Ldarg_0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be even simplified by CollectionAssert.AreEqual()
I'm still workin on one more linq2db test. But there is see, MsCompiler can also line parameterd lambdas |
I've now a Problem with ldarga.s In the Lambda a Method is Called "ConvertString" wich gets a Int as a Parameter wich is a argument. Our Code now emits ldarga.s but Microsoft code emits ldarg.s
This now returns true but should return false, any idea how to fix? |
I've added a test |
I've added a fix, don't know if it's correct ;-( And if it's correct I think we need to hand over this parameter through every try emit call (like the others) |
I have started the work on combining all this parameters into enum flags. So far, so good. Much easy to trace the code and find the patterns - and simplify some parts. So this new parameter will be just an another flag, no need to change parameters through all calls. Plus I have started to inline things were possible. e.g. TryEmitMany and TryEmitBinary. It localize the code checks, in some places they even not required anymore. Will see how it goes. |
do not yet merge, I'm workin on an issue with struct types when ldflda instead of lddld has tu be used. But I need to find out when |
Won't do. May be will ask you for rebase when I done with my changes. |
Info when to use Ldloc vs LdlocA https://stackoverflow.com/questions/4273331/ldloc-or-ldloca |
Only one Linq2db test atm now fails on my system. But 3 times I thought now I had the problem and it's still there. (It's a huge Expression, so the 3 problems were errors we had, but there are still some left) |
@dadhi how far did you get with your refactoring? |
I have finished mechanically, but a big amount of test fails. Will try to fix, and optimize my refactoring tomorrow. |
@jogibear9988
The problem will be to merge this PR, cause some methods were inlined. |
i look to fix tonight |
var byRefIndex = argExprs[i].Type.IsByRef ? i : -1; | ||
if (!TryEmit(argExprs[i], paramExprs, il, ref closure, parent & ~ParentFlags.IgnoreResult, byRefIndex)) | ||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dzmitry-lahoda do you think this is a correct fix ?
IgnoreResult = 1 << 1, | ||
Call = 1 << 2, | ||
MemberAccess = 1 << 3, | ||
MemberAccess = 1 << 3, // Any Parent Expression is a MemberExpression |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding your comment here, parent flags currently are propagated through nested expressions until changed. That means it is more of an ancestor than a parent.
But we may reset the parent in TryEmit when we go deeper. It was my initial variant. Then I removed the reset and nothing changed. So if you found test where it does not work, we may need return reset back:
internal static ParentFlags Reset(ParentFlags p) =>
p & (ParentFlags.IgnoreResult);
Should we preserve IsInstanceAccess
as well?
|
||
public bool HasClosure => ClosureType != null; | ||
|
||
public bool LastEmitIsAddress; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make it into ParentFlags?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's used from the Caller
var notExpr = (UnaryExpression)expr; | ||
if (!TryEmit(notExpr.Operand, paramExprs, il, ref closure, parent)) | ||
return false; | ||
if ((parent & ParentFlags.IgnoreResult) > 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This IL emit may be moved to a method.
|
||
var asAddress = | ||
paramType.IsValueType() && !paramExpr.IsByRef && | ||
(parent & (ParentFlags.Call | ParentFlags.MemberAccess)) != 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, my fail :(
Thanks for fixing.
var locT = il.DeclareLocal(targetType); | ||
il.Emit(OpCodes.Stloc_S, loc); | ||
il.Emit(OpCodes.Ldloca_S, loc); | ||
var hasValueMethod = sourceTypeInfo.GetDeclaredMethod("get_HasValue"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a method for this in Tools.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FindNullableHasValueGetterMethod or something
return false; | ||
il.Emit(OpCodes.Brfalse, labelFalse); | ||
il.Emit(OpCodes.Ldloca_S, loc); | ||
var mthValue = sourceTypeInfo.GetDeclaredMethods("GetValueOrDefault") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
..the same, there is method in Tools.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FindNullableGetValueOrDefaultMethod or something
I still have a bug in the Linq2db Tests, wich I need to find. So do not merge yet |
ok |
var idx = argExprs[i].Type.IsByRef ? i : -1; | ||
if (!TryEmit(argExprs[i], paramExprs, il, ref closure, parent, idx)) | ||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dzmitry-lahoda again, is this correct fix for new with byref?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep. Originally I missed that in .NET there is more then one way to call method
(usual, and via delegate and via ctor).
The code is required because of System.Compile represents Closure as FEC up to some number of items represents closure as typed But after some amount of items, FEC starts to use Here the code in constructing closure which decides what to use: FastExpressionCompiler/src/FastExpressionCompiler/FastExpressionCompiler.cs Lines 441 to 460 in 49294ea
You may comment the methods here to enforce |
74a1979
to
1889265
Compare
@jogibear9988 Hi, it is an amazing thread of work. |
You can merge. linq2db Tests now work except 3, this 3 did also not work before your refactoring. I#m still looking to get them working, but it's a huge expression tree wich I need to pack into a test! |
You also then can close the other 2 pull req. I've included them in mine and fixed the issues |
No description provided.