Browse Source

Fix `stackalloc char[4]` turning to `stackalloc short[4]`.

pull/4091/head
Daniel Grunwald 1 week ago
parent
commit
fb9ff796da
  1. 1
      .gitignore
  2. 13
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS73_StackAllocInitializers.cs
  3. 8
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  4. 2
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

1
.gitignore vendored

@ -22,6 +22,7 @@ ILSpy.Installer/wix/
**/.vscode/ **/.vscode/
DecompilerTests.config.json DecompilerTests.config.json
*.trx *.trx
report/
# Claude Code local session/skills directory # Claude Code local session/skills directory
/.claude/ /.claude/
/.understand-anything /.understand-anything

13
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS73_StackAllocInitializers.cs

@ -332,6 +332,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return UseSpan(span); return UseSpan(span);
} }
public string GetSpan5()
{
Span<char> span = stackalloc char[4] { '1', '2', '3', '4' };
return UseSpan(span);
}
public void Issue2103a() public void Issue2103a()
{ {
Span<byte> span = stackalloc byte[3] { 1, 2, 3 }; Span<byte> span = stackalloc byte[3] { 1, 2, 3 };
@ -354,12 +360,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine((stackalloc byte[3])[1]); Console.WriteLine((stackalloc byte[3])[1]);
} }
public string UseSpan(Span<int> span) public string UseSpan<T>(Span<T> span)
{
throw new NotImplementedException();
}
public string UseSpan(Span<decimal> span)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

8
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -586,11 +586,11 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitLocAllocSpan(LocAllocSpan inst, TranslationContext context) protected internal override TranslatedExpression VisitLocAllocSpan(LocAllocSpan inst, TranslationContext context)
{ {
return TranslateLocAllocSpan(inst, context.TypeHint, out _) return TranslateLocAllocSpan(inst, out _)
.WithILInstruction(inst).WithRR(new ResolveResult(inst.Type)); .WithILInstruction(inst).WithRR(new ResolveResult(inst.Type));
} }
StackAllocExpression TranslateLocAllocSpan(LocAllocSpan inst, IType typeHint, out IType elementType) StackAllocExpression TranslateLocAllocSpan(LocAllocSpan inst, out IType elementType)
{ {
elementType = inst.Type.TypeArguments[0]; elementType = inst.Type.TypeArguments[0];
TranslatedExpression countExpression = Translate(inst.Argument) TranslatedExpression countExpression = Translate(inst.Argument)
@ -3985,6 +3985,8 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
final = spanCtor.Arguments[0] as LdLoc; final = spanCtor.Arguments[0] as LdLoc;
resultType = spanCtor.Method.DeclaringType; resultType = spanCtor.Method.DeclaringType;
// The following function expects typeHint to be a pointer type.
typeHint = new PointerType(spanCtor.Method.DeclaringType.TypeArguments[0]);
} }
if (stloc == null || final == null || stloc.Variable != final.Variable || stloc.Variable.Kind != VariableKind.InitializerTarget) if (stloc == null || final == null || stloc.Variable != final.Variable || stloc.Variable.Kind != VariableKind.InitializerTarget)
throw new ArgumentException("given Block is invalid!"); throw new ArgumentException("given Block is invalid!");
@ -4008,7 +4010,7 @@ namespace ICSharpCode.Decompiler.CSharp
stackAllocExpression = TranslateLocAlloc(locAlloc, typeHint, out elementType); stackAllocExpression = TranslateLocAlloc(locAlloc, typeHint, out elementType);
break; break;
case LocAllocSpan locAllocSpan: case LocAllocSpan locAllocSpan:
stackAllocExpression = TranslateLocAllocSpan(locAllocSpan, typeHint, out elementType); stackAllocExpression = TranslateLocAllocSpan(locAllocSpan, out elementType);
break; break;
default: default:
throw new ArgumentException("given Block is invalid!"); throw new ArgumentException("given Block is invalid!");

2
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -414,6 +414,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
if (!initializer.Instructions[0].MatchStLoc(out var initializerVariable, out var value)) if (!initializer.Instructions[0].MatchStLoc(out var initializerVariable, out var value))
return false; return false;
if (!TypeUtils.IsCompatiblePointerTypeForMemoryAccess(initializerVariable.Type, elementType))
return false;
if (!(value.MatchLocAlloc(out sizeInBytes) && MatchesElementCount(sizeInBytes, elementType, newObj.Arguments[1]))) if (!(value.MatchLocAlloc(out sizeInBytes) && MatchesElementCount(sizeInBytes, elementType, newObj.Arguments[1])))
return false; return false;
// The block addresses the allocation through the localloc pointer and only its // The block addresses the allocation through the localloc pointer and only its

Loading…
Cancel
Save