-
Notifications
You must be signed in to change notification settings - Fork 847
Support SkipLocalsinit #11267
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
Support SkipLocalsinit #11267
Conversation
|
Looks straight forward so far. But yea you are right, the |
|
Do I just create a test file similar to https://github.com/dotnet/fsharp/blob/main/tests/FSharp.Compiler.ComponentTests/EmittedIL/TailCalls.fs or do I have to muck around with stuff like this https://github.com/dotnet/fsharp/tree/main/tests/fsharpqa/Source/CodeGen/EmittedIL? |
Creating a test in ComponentTests suite should be fine. |
|
@vzarytovskii, the problem here is the fact that the attribute is .NET 5+ only, so the test snippet needs to be compiled against that TFM. What now? |
|
It looks like the test only failed during the net472 run, so one option is running the test behind something like |
|
Or maybe I'm misunderstanding things and the net472 version of fsc cannot compile code for .NET Core? |
| member val attrib_CallerLineNumberAttribute = findSysAttrib "System.Runtime.CompilerServices.CallerLineNumberAttribute" | ||
| member val attrib_CallerFilePathAttribute = findSysAttrib "System.Runtime.CompilerServices.CallerFilePathAttribute" | ||
| member val attrib_CallerMemberNameAttribute = findSysAttrib "System.Runtime.CompilerServices.CallerMemberNameAttribute" | ||
| member val attrib_SkipLocalsInitAttribute = findSysAttrib "System.Runtime.CompilerServices.SkipLocalsInitAttribute" |
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'm not quite sure if this shouldn't be tryFindSysAttrib. Attributes above use both find and try find and I can't tell what the deciding factor is. It does not throw even on net472, so I guess it's fine?
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 is fine. You can check to see if you can deref it. If you can't, then it couldn't find it.
|
@TIHan, got it. Methods don't get the class's Lines 6894 to 6901 in 04ef067
Tests pass when run on against .NET 5, so this is ready for review. I don't know what to do about 'Build Windows desktop_release'. |
|
I'd appreciate help with that test. |
|
Apologies for the delay. I will find time today to look at this. I've been doing similar stuff in IlxGen lately. |
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 looks great! You don't have to worry about checking for a deref on the attribute; HasFSharpAttribute will return false if the SkipLocalsInitAttribute could not be found in the framework.
In regards to the test, you can put a #if NETCOREAPP around the test so it will only run on netcore and not framework.
|
Thanks, hopefully it's green and ready to go now. |
cartermp
left a comment
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 think this looks good, but should it also be backed by LangVersion? It's not really a new feature per say, just respecting an existing attribute. So I say it's not necessary. But I'm happy to hear arguments otherwise.
vzarytovskii
left a comment
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.
Thanks!
| open Xunit | ||
| open FSharp.Test.Utilities.Compiler | ||
|
|
||
| #if NETCOREAPP |
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.
That should be good testing wise, I'll see what we can do with the x-framework IL validation.
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.
It would be great if you could pass TFM to compile because the .NET Framework version of the compiler needs to be able to compile code like this, so it makes sense to test it too, but I understand a bit of infrastructure plumbing work may be required. Plus it will also help with cases where binaries for different TFMs end up with slightly different IL, making these tests tricky, as I've mentioned elsewhere.
|
On the off chance that you're waiting to hear my opinion, I don't think LangVersion is needed either. The attribute is fairly new and, more importantly, currently has no impact in F#, so I find it extremely unlikely there's code out there that uses it. The risks (someone using That's assuming the design (primarily the way the attribute affects types, methods, nested functions and lambdas) is final. |
|
Agreed. Let's merge it! |
|
There is a problem here We use locals zero init to generate default values of arbitrary value types here: You should change the However that leaves a separate problem about how to generate a zero byref value, because from the comment |
|
This code [<System.Runtime.CompilerServices.SkipLocalsInit>]
let z () =
let mutable a = Unchecked.defaultof<System.DateTime>
a <- Unchecked.defaultof<System.DateTime>generates With Is that what you want to see? I'm not sure I follow your second point. If the compiler didn't generate init code for byrefs before, why would |
|
Ah, perhaps you want to always zero init when locals are no longer initialized, so |
|
I think you want |
|
Ok, will send a PR with a test for this. |
Implements fsharp/fslang-suggestions#990.
When applied on a module, class or method/function, all nested methods/functions and lambdas must not set the
.locals initflag (paraphrased based on docs).This naive implementation assumes that locals should be initialized by default unless stated otherwise, though that may change in the future. It seems to work well at first glance with the exception of using the attribute on a class. The
eenvinnerinGenTypeDefcorrectly recognizes that locals should not be initialized, but the env instance is supposedly not passed down toGenMethodForBindingfor the class' instance and static methods, unlike when the attribute is used on an entire module. Any clues?Please let me know if what I did makes sense. I'll also need some pointers on authoring tests for this kind of thing.