Browse Source

Drop the bool result of the localloc prefix handler

A true result meant both 'consumed a prefix' and 'no prefix present',
while false aborted the whole transform. The distinction is unnecessary:
a malformed or absent prefix leaves pos unchanged, so the per-element
stobj scan fails on the initblk/cpblk instruction and rejects the
transform with the same out-state. Aborting on 'no prefix' had also
broken plain constant-length stackalloc initializers (element stores
without any prefix), caught by CS73_StackAllocInitializers.

Assisted-by: Claude:claude-fable-5:Claude Code
master
Siegfried Pammer 2 days ago committed by Siegfried Pammer
parent
commit
587c55ca05
  1. 22
      ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs

22
ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs

@ -428,10 +428,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -428,10 +428,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
BlobReader blob = default;
if (lengthInstruction.MatchLdcI(out long byteCount)
&& !TryHandleLocAllocInitializerPrefix(block, ref pos, store, byteCount, ref blob, ref instructionsToRemove))
if (lengthInstruction.MatchLdcI(out long byteCount))
{
return false;
// An initblk/cpblk that does not fit the expected shape is left in place;
// the per-element stobj scan below then fails to match it and rejects the
// transform on its own.
HandleLocAllocInitializerPrefix(block, ref pos, store, byteCount, ref blob, ref instructionsToRemove);
}
for (int i = pos; i < block.Instructions.Count; i++)
@ -499,34 +501,32 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -499,34 +501,32 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return elementCount <= values.Length;
}
bool TryHandleLocAllocInitializerPrefix(Block block, ref int pos, ILVariable store, long byteCount, ref BlobReader blob, ref int instructionsToRemove)
void HandleLocAllocInitializerPrefix(Block block, ref int pos, ILVariable store, long byteCount, ref BlobReader blob, ref int instructionsToRemove)
{
// initblk(ldloc store, value, byteCount)
if (block.Instructions[pos].MatchInitblk(out var dest, out _, out var size))
{
if (!dest.MatchLdLoc(store) || !size.MatchLdcI(byteCount))
return false;
return;
instructionsToRemove++;
pos++;
return true;
return;
}
// cpblk(ldloc store, ldsflda/call get_Item(CreateSpan(field)) data, byteCount)
if (block.Instructions[pos].MatchCpblk(out dest, out var src, out size))
{
if (!dest.MatchLdLoc(store) || !size.MatchLdcI(byteCount))
return false;
return;
if (!MatchGetStaticFieldAddress(src, out var field))
return false;
return;
var fd = context.PEFile.Metadata.GetFieldDefinition((FieldDefinitionHandle)field.MetadataToken);
if (!fd.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA))
return false;
return;
blob = fd.GetInitialValue(context.PEFile, context.TypeSystem);
instructionsToRemove++;
pos++;
}
return true;
}
static bool TryGetSequentialStoreOffset(ILInstruction target, ILVariable store, IType elementType, long minExpectedOffset, out long offset, out bool abortTransform)

Loading…
Cancel
Save