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. 16
      ICSharpCode.Decompiler/IL/Transforms/SplitVariables.cs

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

@ -150,12 +150,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// unless we can see an address being returned from the method: // unless we can see an address being returned from the method:
IType returnType = (call is NewObj) ? call.Method.DeclaringType : call.Method.ReturnType; IType returnType = (call is NewObj) ? call.Method.DeclaringType : call.Method.ReturnType;
if (returnType.IsByRefLike) if (returnType.IsByRefLike)
{
// 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. // 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'. // 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) if (DetermineAddressUse(call, targetVar) != AddressUse.Immediate)
return AddressUse.Unknown; return AddressUse.Unknown;
} }
}
foreach (var p in call.Method.Parameters) foreach (var p in call.Method.Parameters)
{ {
// catch "out Span<int>" and similar // catch "out Span<int>" and similar
@ -174,6 +180,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return AddressUse.Immediate; 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> /// <summary>
/// Given 'ldloc ref_local' and 'ldloca target; stloc ref_local', returns the ldloca. /// 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. /// This function must return a non-null LdLoca for every use of a SupportedRefLocal.

Loading…
Cancel
Save