Browse Source

Allow variable splitting of compiler-generated temporaries for Span<T>/ROS<T>

feature/inlinearrays
Siegfried Pammer 2 months ago
parent
commit
cb790c6d38
  1. 24
      ICSharpCode.Decompiler/IL/Transforms/SplitVariables.cs

24
ICSharpCode.Decompiler/IL/Transforms/SplitVariables.cs

@ -151,11 +151,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -151,11 +151,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms
IType returnType = (call is NewObj) ? call.Method.DeclaringType : call.Method.ReturnType;
if (returnType.IsByRefLike)
{
// If the address is returned from the method, it check whether it's consumed immediately.
// This can still be fine, as long as we also check the consumer's other arguments for 'stloc targetVar'.
if (DetermineAddressUse(call, targetVar) != AddressUse.Immediate)
return AddressUse.Unknown;
// We exclude Span<T>.Item[int index] and ReadOnlySpan<T>.Item[int index], because it is known that this
// or members of this cannot be returned by the method.
if (!IsSpanOfTIndexerAccessor(call.Method))
{
// If the address is returned from the method, it check whether it's consumed immediately.
// This can still be fine, as long as we also check the consumer's other arguments for 'stloc targetVar'.
if (DetermineAddressUse(call, targetVar) != AddressUse.Immediate)
return AddressUse.Unknown;
}
}
foreach (var p in call.Method.Parameters)
{
// catch "out Span<int>" and similar
@ -174,6 +180,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -174,6 +180,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return AddressUse.Immediate;
}
static bool IsSpanOfTIndexerAccessor(IMethod method)
{
var declaringType = method.DeclaringType;
if (!declaringType.IsKnownType(KnownTypeCode.SpanOfT)
&& !declaringType.IsKnownType(KnownTypeCode.ReadOnlySpanOfT))
return false;
return method.AccessorOwner is IProperty { IsIndexer: true, Name: "Item", Parameters: [var param], ReturnType: ByReferenceType { ElementType: var rt } }
&& param.Type.IsKnownType(KnownTypeCode.Int32) && rt.Equals(declaringType.TypeArguments[0]);
}
/// <summary>
/// Given 'ldloc ref_local' and 'ldloca target; stloc ref_local', returns the ldloca.
/// This function must return a non-null LdLoca for every use of a SupportedRefLocal.

Loading…
Cancel
Save