Skip to content

Commit 60832e2

Browse files
Allow variable splitting of compiler-generated temporaries for Span<T>/ROS<T>
1 parent aff9649 commit 60832e2

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

ICSharpCode.Decompiler/IL/Transforms/SplitVariables.cs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,17 @@ static AddressUse HandleCall(ILInstruction addressLoadingInstruction, ILVariable
151151
IType returnType = (call is NewObj) ? call.Method.DeclaringType : call.Method.ReturnType;
152152
if (returnType.IsByRefLike)
153153
{
154-
// If the address is returned from the method, it check whether it's consumed immediately.
155-
// This can still be fine, as long as we also check the consumer's other arguments for 'stloc targetVar'.
156-
if (DetermineAddressUse(call, targetVar) != AddressUse.Immediate)
157-
return AddressUse.Unknown;
154+
// We exclude Span<T>.Item[int index] and ReadOnlySpan<T>.Item[int index], because it is known that this
155+
// or members of this cannot be returned by the method.
156+
if (!IsSpanOfTIndexerAccessor(call.Method))
157+
{
158+
// If the address is returned from the method, it check whether it's consumed immediately.
159+
// This can still be fine, as long as we also check the consumer's other arguments for 'stloc targetVar'.
160+
if (DetermineAddressUse(call, targetVar) != AddressUse.Immediate)
161+
return AddressUse.Unknown;
162+
}
158163
}
164+
159165
foreach (var p in call.Method.Parameters)
160166
{
161167
// catch "out Span<int>" and similar
@@ -174,6 +180,16 @@ static AddressUse HandleCall(ILInstruction addressLoadingInstruction, ILVariable
174180
return AddressUse.Immediate;
175181
}
176182

183+
static bool IsSpanOfTIndexerAccessor(IMethod method)
184+
{
185+
var declaringType = method.DeclaringType;
186+
if (!declaringType.IsKnownType(KnownTypeCode.SpanOfT)
187+
&& !declaringType.IsKnownType(KnownTypeCode.ReadOnlySpanOfT))
188+
return false;
189+
return method.AccessorOwner is IProperty { IsIndexer: true, Name: "Item", Parameters: [var param], ReturnType: ByReferenceType { ElementType: var rt } }
190+
&& param.Type.IsKnownType(KnownTypeCode.Int32) && rt.Equals(declaringType.TypeArguments[0]);
191+
}
192+
177193
/// <summary>
178194
/// Given 'ldloc ref_local' and 'ldloca target; stloc ref_local', returns the ldloca.
179195
/// This function must return a non-null LdLoca for every use of a SupportedRefLocal.

0 commit comments

Comments
 (0)