Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/Compiler/AbstractIL/il.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2113,6 +2113,11 @@ type ILMethodDef
x.ImplAttributes &&& MethodImplAttributes.AggressiveInlining <> enum 0

member x.IsMustRun = x.ImplAttributes &&& MethodImplAttributes.NoOptimization <> enum 0

// Async is defined as 0x2000 or 8192
// https://github.com/dotnet/runtime/blob/main/docs/design/specs/runtime-async.md
member x.IsAsync =
x.ImplAttributes &&& enum (0x2000) <> enum 0

member x.WithSpecialName =
x.With(attributes = (x.Attributes ||| MethodAttributes.SpecialName))
Expand Down Expand Up @@ -2170,6 +2175,9 @@ type ILMethodDef
|> conditionalAdd condition MethodImplAttributes.AggressiveInlining)
)

member x.WithAsync(condition) =
x.With(implAttributes = (x.ImplAttributes |> conditionalAdd condition (enum 0x2000)))

member x.WithRuntime(condition) =
x.With(implAttributes = (x.ImplAttributes |> conditionalAdd condition MethodImplAttributes.Runtime))

Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/AbstractIL/il.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,9 @@ type ILMethodDef =
/// SafeHandle finalizer must be run.
member IsMustRun: bool

/// https://github.com/dotnet/runtime/blob/main/docs/design/specs/runtime-async.md
member IsAsync: bool

/// Functional update of the value
member internal With:
?name: string *
Expand Down Expand Up @@ -1200,6 +1203,8 @@ type ILMethodDef =

member internal WithAggressiveInlining: bool -> ILMethodDef

member internal WithAsync: bool -> ILMethodDef

member internal WithRuntime: bool -> ILMethodDef

/// Tables of methods. Logically equivalent to a list of methods but
Expand Down
4 changes: 4 additions & 0 deletions src/Compiler/AbstractIL/ilprint.fs
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,9 @@ let goutput_mbody is_entrypoint env os (md: ILMethodDef) =
output_string os "native "
elif md.ImplAttributes &&& MethodImplAttributes.IL <> enum 0 then
output_string os "cil "
if md.IsAsync then
output_string os "async "

else
output_string os "runtime "

Expand Down Expand Up @@ -728,6 +731,7 @@ let goutput_mdef env os (md: ILMethodDef) =
if md.IsAggressiveInline then
output_string os "aggressiveinlining "


(goutput_mbody is_entrypoint menv) os md
output_string os "\n"

Expand Down
9 changes: 6 additions & 3 deletions src/Compiler/CodeGen/IlxGen.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9148,7 +9148,8 @@ and ComputeMethodImplAttribs cenv (_v: Val) attrs =
let hasSynchronizedImplFlag = (implflags &&& 0x20) <> 0x0
let hasNoInliningImplFlag = (implflags &&& 0x08) <> 0x0
let hasAggressiveInliningImplFlag = (implflags &&& 0x0100) <> 0x0
hasPreserveSigImplFlag, hasSynchronizedImplFlag, hasNoInliningImplFlag, hasAggressiveInliningImplFlag, attrs
let hasAsyncImplFlag = (implflags &&& 0x2000) <> 0x0
hasPreserveSigImplFlag, hasSynchronizedImplFlag, hasNoInliningImplFlag, hasAggressiveInliningImplFlag, hasAsyncImplFlag, attrs

and GenMethodForBinding
cenv
Expand Down Expand Up @@ -9332,7 +9333,7 @@ and GenMethodForBinding
| _ -> [], None

// check if the hasPreserveSigNamedArg and hasSynchronizedImplFlag implementation flags have been specified
let hasPreserveSigImplFlag, hasSynchronizedImplFlag, hasNoInliningFlag, hasAggressiveInliningImplFlag, attrs =
let hasPreserveSigImplFlag, hasSynchronizedImplFlag, hasNoInliningFlag, hasAggressiveInliningImplFlag, hasAsyncImplFlag, attrs =
ComputeMethodImplAttribs cenv v attrs

let securityAttributes, attrs =
Expand Down Expand Up @@ -9607,6 +9608,7 @@ and GenMethodForBinding
.WithSynchronized(hasSynchronizedImplFlag)
.WithNoInlining(hasNoInliningFlag)
.WithAggressiveInlining(hasAggressiveInliningImplFlag)
.WithAsync(hasAsyncImplFlag)
.With(isEntryPoint = isExplicitEntryPoint, securityDecls = secDecls)

let mdef =
Expand Down Expand Up @@ -10673,7 +10675,7 @@ and GenAbstractBinding cenv eenv tref (vref: ValRef) =
let memberInfo = Option.get vref.MemberInfo
let attribs = vref.Attribs

let hasPreserveSigImplFlag, hasSynchronizedImplFlag, hasNoInliningFlag, hasAggressiveInliningImplFlag, attribs =
let hasPreserveSigImplFlag, hasSynchronizedImplFlag, hasNoInliningFlag, hasAggressiveInliningImplFlag, hasAsyncImplFlag, attribs =
ComputeMethodImplAttribs cenv vref.Deref attribs

if memberInfo.MemberFlags.IsDispatchSlot && not memberInfo.IsImplemented then
Expand Down Expand Up @@ -10727,6 +10729,7 @@ and GenAbstractBinding cenv eenv tref (vref: ValRef) =
.WithSynchronized(hasSynchronizedImplFlag)
.WithNoInlining(hasNoInliningFlag)
.WithAggressiveInlining(hasAggressiveInliningImplFlag)
.WithAsync(hasAsyncImplFlag)

match memberInfo.MemberFlags.MemberKind with
| SynMemberKind.ClassConstructor
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Regression test for DevDiv:212424
// "NoInlining attribute not emitted into IL"
module M
open System.Threading.Tasks
open System.Runtime.CompilerServices
[<System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.Async)>]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this will fail when targeting desktop framework, you might need to use TheoryForNETCOREAPPAttribute in the test declaration.

let getUnit (f : unit -> Task<unit>) = AsyncHelpers.Await(f())
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@





.assembly extern runtime { }
.assembly extern FSharp.Core { }
.assembly assembly
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
int32,
int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )




.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module assembly.exe

.imagebase {value}
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003
.corflags 0x00000001





.class public abstract auto ansi sealed M
extends [runtime]System.Object
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
.method public static void getUnit(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [runtime]System.Threading.Tasks.Task`1<class [FSharp.Core]Microsoft.FSharp.Core.Unit>> f) cil managed async
{

.maxstack 8
IL_0000: ldarg.0
IL_0001: ldnull
IL_0002: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [runtime]System.Threading.Tasks.Task`1<class [FSharp.Core]Microsoft.FSharp.Core.Unit>>::Invoke(!0)
IL_0007: call !!0 [runtime]System.Runtime.CompilerServices.AsyncHelpers::Await<class [FSharp.Core]Microsoft.FSharp.Core.Unit>(class [runtime]System.Threading.Tasks.Task`1<!!0>)
IL_000c: pop
IL_000d: ret
}

}

.class private abstract auto ansi sealed '<StartupCode$MethodImplAttribute-Async>'.$M
extends [runtime]System.Object
{
.method public static void main@() cil managed
{
.entrypoint

.maxstack 8
IL_0000: ret
}

}






Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ module MethodImplAttribute =
compilation
|> getCompilation
|> verifyCompilation


// SOURCE=MethodImplAttribute.Async.fs SCFLAGS="-a -g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd MethodImplAttribute.Async.dll" # MethodImplAttribute.Async.fs
[<Theory; FileInlineData("MethodImplAttribute.Async.fs")>]
let ``Async_fs`` compilation =
compilation
|> getCompilation
|> verifyCompilation


// SOURCE=MethodImplAttribute.NoOptimization.fs SCFLAGS="-a -g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd MethodImplAttribute.NoOptimization.dll" # MethodImplAttribute.NoOptimization.fs
[<Theory; FileInlineData("MethodImplAttribute.NoOptimization.fs")>]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,7 @@ FSharp.Compiler.AbstractIL.IL+ILMemberAccess: System.String ToString()
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean HasSecurity
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean IsAbstract
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean IsAggressiveInline
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean IsAsync
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean IsCheckAccessOnOverride
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean IsClassInitializer
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean IsConstructor
Expand All @@ -779,6 +780,7 @@ FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean IsZeroInit
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean get_HasSecurity()
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean get_IsAbstract()
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean get_IsAggressiveInline()
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean get_IsAsync()
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean get_IsCheckAccessOnOverride()
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean get_IsClassInitializer()
FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean get_IsConstructor()
Expand Down
Loading