Skip to content

Commit

Permalink
Fixed generated IL
Browse files Browse the repository at this point in the history
  • Loading branch information
svick committed Oct 14, 2021
1 parent b3dc83e commit 804a997
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ private void EmitStackAlloc(TypeSymbol type, BoundArrayInitialization? inits, Bo
}
else
{
_builder.EmitStackAllocBlockMultiByteInitializer(data, elementType.GetPublicSymbol(), inits.Syntax, _diagnostics);
EmitStackAllocBlockMultiByteInitializer(data, elementType, inits.Syntax, _diagnostics);
}
}

Expand All @@ -94,6 +94,30 @@ void emitLocalloc()
}
}

private void EmitStackAllocBlockMultiByteInitializer(ImmutableArray<byte> data, TypeSymbol elementType, SyntaxNode syntaxNode, DiagnosticBag diagnostics)
{
// get helpers
var definition = (MethodSymbol)_module.Compilation.GetWellKnownTypeMember(WellKnownMember.System_ReadOnlySpan_T__GetPinnableReference)!;
var getPinnableReference = definition.AsMember(definition.ContainingType.Construct(elementType)).GetCciAdapter();
var readOnlySpan = ((NamedTypeSymbol)_module.Compilation.CommonGetWellKnownType(WellKnownType.System_ReadOnlySpan_T)).GetCciAdapter();

// emit call to the helper
_builder.EmitOpCode(ILOpCode.Dup);
_builder.EmitCreateSpan(data, elementType.GetPublicSymbol(), syntaxNode, diagnostics);

var temp = _builder.LocalSlotManager.AllocateSlot(readOnlySpan, LocalSlotConstraints.None);
_builder.EmitLocalStore(temp);
_builder.EmitLocalAddress(temp);
_builder.LocalSlotManager.FreeSlot(temp);

// TODO: is this safe without pinning?
_builder.EmitOpCode(ILOpCode.Call, 0);
_builder.EmitToken(getPinnableReference, syntaxNode, diagnostics);
_builder.EmitIntConstant(data.Length);
// TODO: is this correct without unaligned.?
_builder.EmitOpCode(ILOpCode.Cpblk, -3);
}

internal static bool UseCreateSpanForReadOnlySpanInitialization(
bool hasCreateSpanHelper, bool considerInitblk, TypeSymbol elementType, BoundArrayInitialization? inits, bool supportsPrivateImplClass) =>
hasCreateSpanHelper && inits?.Initializers is { } initExprs &&
Expand Down
12 changes: 0 additions & 12 deletions src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -827,18 +827,6 @@ public sealed override Cci.IMethodReference GetCreateSpanHelper(ITypeSymbol elem
?.Construct(csharpElementType).GetCciAdapter();
}

public sealed override Cci.IMethodReference GetReadOnlySpanGetPinnableReference(ITypeSymbol elementType)
{
if ((elementType as Symbols.PublicModel.TypeSymbol)?.UnderlyingTypeSymbol is not { } csharpElementType)
{
return null;
}

var definition = (MethodSymbol)Compilation.GetWellKnownTypeMember(WellKnownMember.System_ReadOnlySpan_T__GetPinnableReference);

return definition?.AsMember(definition.ContainingType.Construct(csharpElementType)).GetCciAdapter();
}

public sealed override bool IsPlatformType(Cci.ITypeReference typeRef, Cci.PlatformType platformType)
{
var namedType = typeRef.GetInternalSymbol() as NamedTypeSymbol;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -853,21 +853,24 @@ static void Write(Span<int> span) {}
.VerifyIL("C.Main",
@"
{
// Code size 37 (0x25)
// Code size 40 (0x28)
.maxstack 4
.locals init (System.ReadOnlySpan<T> V_0)
IL_0000: ldc.i4.s 12
IL_0002: conv.u
IL_0003: localloc
IL_0005: dup
IL_0006: ldtoken ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=12 <PrivateImplementationDetails>.4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D""
IL_000b: call ""System.ReadOnlySpan<int> System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan<int>(System.RuntimeFieldHandle)""
IL_0010: call ""ref readonly int System.ReadOnlySpan<int>.GetPinnableReference()""
IL_0015: ldc.i4.s 12
IL_0017: cpblk
IL_0019: ldc.i4.3
IL_001a: newobj ""System.Span<int>..ctor(void*, int)""
IL_001f: call ""void C.Write(System.Span<int>)""
IL_0024: ret
IL_0010: stloc.0
IL_0011: ldloca.s V_0
IL_0013: call ""ref readonly int System.ReadOnlySpan<int>.GetPinnableReference()""
IL_0018: ldc.i4.s 12
IL_001a: cpblk
IL_001c: ldc.i4.3
IL_001d: newobj ""System.Span<int>..ctor(void*, int)""
IL_0022: call ""void C.Write(System.Span<int>)""
IL_0027: ret
}
");
}
Expand Down Expand Up @@ -922,19 +925,22 @@ static void Write(int* span) {}
.VerifyIL("C.Main",
@"
{
// Code size 31 (0x1f)
// Code size 34 (0x22)
.maxstack 4
.locals init (System.ReadOnlySpan<T> V_0)
IL_0000: ldc.i4.s 12
IL_0002: conv.u
IL_0003: localloc
IL_0005: dup
IL_0006: ldtoken ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=12 <PrivateImplementationDetails>.4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D""
IL_000b: call ""System.ReadOnlySpan<int> System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan<int>(System.RuntimeFieldHandle)""
IL_0010: call ""ref readonly int System.ReadOnlySpan<int>.GetPinnableReference()""
IL_0015: ldc.i4.s 12
IL_0017: cpblk
IL_0019: call ""void C.Write(int*)""
IL_001e: ret
IL_0010: stloc.0
IL_0011: ldloca.s V_0
IL_0013: call ""ref readonly int System.ReadOnlySpan<int>.GetPinnableReference()""
IL_0018: ldc.i4.s 12
IL_001a: cpblk
IL_001c: call ""void C.Write(int*)""
IL_0021: ret
}
");
}
Expand All @@ -959,30 +965,33 @@ static void Write(ReadOnlySpan<int> span) {}
.VerifyIL("C.Main",
@"
{
// Code size 50 (0x32)
// Code size 53 (0x35)
.maxstack 4
.locals init (System.ReadOnlySpan<T> V_0)
IL_0000: ldc.i4.s 16
IL_0002: conv.u
IL_0003: localloc
IL_0005: dup
IL_0006: ldtoken ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=16 <PrivateImplementationDetails>.81C1A5A2F482E82CA2C66653482AB24E6D90944BF183C8164E8F8F8D72DB60DB""
IL_000b: call ""System.ReadOnlySpan<int> System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan<int>(System.RuntimeFieldHandle)""
IL_0010: call ""ref readonly int System.ReadOnlySpan<int>.GetPinnableReference()""
IL_0015: ldc.i4.s 16
IL_0017: cpblk
IL_0019: dup
IL_001a: ldc.i4.3
IL_001b: conv.i
IL_001c: ldc.i4.4
IL_001d: mul
IL_001e: add
IL_001f: ldarg.0
IL_0020: stind.i4
IL_0021: ldc.i4.4
IL_0022: newobj ""System.Span<int>..ctor(void*, int)""
IL_0027: call ""System.ReadOnlySpan<int> System.Span<int>.op_Implicit(System.Span<int>)""
IL_002c: call ""void C.Write(System.ReadOnlySpan<int>)""
IL_0031: ret
IL_0010: stloc.0
IL_0011: ldloca.s V_0
IL_0013: call ""ref readonly int System.ReadOnlySpan<int>.GetPinnableReference()""
IL_0018: ldc.i4.s 16
IL_001a: cpblk
IL_001c: dup
IL_001d: ldc.i4.3
IL_001e: conv.i
IL_001f: ldc.i4.4
IL_0020: mul
IL_0021: add
IL_0022: ldarg.0
IL_0023: stind.i4
IL_0024: ldc.i4.4
IL_0025: newobj ""System.Span<int>..ctor(void*, int)""
IL_002a: call ""System.ReadOnlySpan<int> System.Span<int>.op_Implicit(System.Span<int>)""
IL_002f: call ""void C.Write(System.ReadOnlySpan<int>)""
IL_0034: ret
}
");
}
Expand Down
16 changes: 0 additions & 16 deletions src/Compilers/Core/Portable/CodeGen/ILBuilderEmit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,22 +119,6 @@ internal void EmitStackAllocBlockSingleByteInitializer(ImmutableArray<byte> data
}
}

internal void EmitStackAllocBlockMultiByteInitializer(ImmutableArray<byte> data, ITypeSymbol elementType, SyntaxNode syntaxNode, DiagnosticBag diagnostics)
{
// get helpers
var getPinnableReference = module.GetReadOnlySpanGetPinnableReference(elementType);

// emit call to the helper
EmitOpCode(ILOpCode.Dup);
EmitCreateSpan(data, elementType, syntaxNode, diagnostics);
// TODO: is this safe without pinning?
EmitOpCode(ILOpCode.Call, 0);
EmitToken(getPinnableReference, syntaxNode, diagnostics);
EmitIntConstant(data.Length);
// TODO: is this correct without unaligned.?
EmitOpCode(ILOpCode.Cpblk, -3);
}

internal void EmitCreateSpan(ImmutableArray<byte> data, ITypeSymbol elementType, SyntaxNode syntaxNode, DiagnosticBag diagnostics)
{
// get helpers
Expand Down
1 change: 0 additions & 1 deletion src/Compilers/Core/Portable/CodeGen/ITokenDeferral.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ internal interface ITokenDeferral
Cci.IFieldReference GetFieldForData(ImmutableArray<byte> data, SyntaxNode syntaxNode, DiagnosticBag diagnostics);
Cci.IMethodReference GetInitArrayHelper();
Cci.IMethodReference GetCreateSpanHelper(ITypeSymbol elementType);
Cci.IMethodReference GetReadOnlySpanGetPinnableReference(ITypeSymbol elementType);

string GetStringFromToken(uint token);
/// <summary>
Expand Down
2 changes: 0 additions & 2 deletions src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -995,8 +995,6 @@ Cci.IFieldReference ITokenDeferral.GetFieldForData(ImmutableArray<byte> data, Sy

public abstract Cci.IMethodReference GetCreateSpanHelper(ITypeSymbol elementType);

public abstract Cci.IMethodReference GetReadOnlySpanGetPinnableReference(ITypeSymbol elementType);

public ArrayMethods ArrayMethods
{
get
Expand Down
11 changes: 0 additions & 11 deletions src/Compilers/VisualBasic/Portable/Emit/PEModuleBuilder.vb
Original file line number Diff line number Diff line change
Expand Up @@ -616,17 +616,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Return DirectCast(Compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__CreateSpan_T), MethodSymbol)?.Construct(vbElementType).GetCciAdapter()
End Function

Public NotOverridable Overrides Function GetReadOnlySpanGetPinnableReference(elementType As ITypeSymbol) As Cci.IMethodReference
Dim vbElementType = TryCast(elementType, TypeSymbol)
If vbElementType Is Nothing Then
Return Nothing
End If

Dim definition = DirectCast(Compilation.GetWellKnownTypeMember(WellKnownMember.System_ReadOnlySpan_T__GetPinnableReference), MethodSymbol)

Return definition?.AsMember(definition.ContainingType.Construct(vbElementType)).GetCciAdapter()
End Function

Public NotOverridable Overrides Function IsPlatformType(typeRef As Cci.ITypeReference, platformType As Cci.PlatformType) As Boolean
Dim namedType = TryCast(typeRef.GetInternalSymbol(), NamedTypeSymbol)

Expand Down

0 comments on commit 804a997

Please sign in to comment.