Skip to content

Commit

Permalink
Use BinaryPrimitives more in the ILCompiler (#105404)
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulusParssinen committed Jul 25, 2024
1 parent 240fd94 commit 5377b58
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 47 deletions.
15 changes: 3 additions & 12 deletions src/coreclr/tools/Common/Pgo/PgoFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Buffers.Binary;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
Expand Down Expand Up @@ -163,22 +164,12 @@ public bool MoveNext()
}
else if ((bytes[offset]) == 0xC1) // 8 byte specifier
{
signedInt = (((long)bytes[offset + 1]) << 56) |
(((long)bytes[offset + 2]) << 48) |
(((long)bytes[offset + 3]) << 40) |
(((long)bytes[offset + 4]) << 32) |
(((long)bytes[offset + 5]) << 24) |
(((long)bytes[offset + 6]) << 16) |
(((long)bytes[offset + 7]) << 8) |
((long)bytes[offset + 8]);
signedInt = BinaryPrimitives.ReadInt64BigEndian(bytes.AsSpan(offset + 1, sizeof(long)));
offset += 9;
}
else
{
signedInt = (((int)bytes[offset + 1]) << 24) |
(((int)bytes[offset + 2]) << 16) |
(((int)bytes[offset + 3]) << 8) |
((int)bytes[offset + 4]);
signedInt = BinaryPrimitives.ReadInt32BigEndian(bytes.AsSpan(offset + 1, sizeof(int)));
offset += 5;
}

Expand Down
13 changes: 7 additions & 6 deletions src/coreclr/tools/Common/TypeSystem/IL/ILDisassembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Buffers.Binary;
using System.Text;

using Internal.TypeSystem;
Expand Down Expand Up @@ -191,15 +192,15 @@ private byte ReadILByte()

private ushort ReadILUInt16()
{
ushort val = (ushort)(_ilBytes[_currentOffset] + (_ilBytes[_currentOffset + 1] << 8));
_currentOffset += 2;
ushort val = BinaryPrimitives.ReadUInt16LittleEndian(_ilBytes.AsSpan(_currentOffset, sizeof(ushort)));
_currentOffset += sizeof(ushort);
return val;
}

private uint ReadILUInt32()
{
uint val = (uint)(_ilBytes[_currentOffset] + (_ilBytes[_currentOffset + 1] << 8) + (_ilBytes[_currentOffset + 2] << 16) + (_ilBytes[_currentOffset + 3] << 24));
_currentOffset += 4;
uint val = BinaryPrimitives.ReadUInt32LittleEndian(_ilBytes.AsSpan(_currentOffset, sizeof(uint)));
_currentOffset += sizeof(uint);
return val;
}

Expand All @@ -211,8 +212,8 @@ private int ReadILToken()

private ulong ReadILUInt64()
{
ulong value = ReadILUInt32();
value |= (((ulong)ReadILUInt32()) << 32);
ulong value = BinaryPrimitives.ReadUInt64LittleEndian(_ilBytes.AsSpan(_currentOffset, sizeof(ulong)));
_currentOffset += sizeof(ulong);
return value;
}

Expand Down
24 changes: 13 additions & 11 deletions src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Buffers.Binary;
using Internal.TypeSystem;

namespace Internal.IL
Expand All @@ -20,30 +22,28 @@ internal sealed partial class ILImporter

private byte ReadILByte()
{
if (_currentOffset >= _ilBytes.Length)
if (_currentOffset + 1 > _ilBytes.Length)
ReportMethodEndInsideInstruction();

return _ilBytes[_currentOffset++];
}

private ushort ReadILUInt16()
{
if (_currentOffset + 1 >= _ilBytes.Length)
if (!BinaryPrimitives.TryReadUInt16LittleEndian(_ilBytes.AsSpan(_currentOffset), out ushort value))
ReportMethodEndInsideInstruction();

ushort val = (ushort)(_ilBytes[_currentOffset] + (_ilBytes[_currentOffset + 1] << 8));
_currentOffset += 2;
return val;
_currentOffset += sizeof(ushort);
return value;
}

private uint ReadILUInt32()
{
if (_currentOffset + 3 >= _ilBytes.Length)
if (!BinaryPrimitives.TryReadUInt32LittleEndian(_ilBytes.AsSpan(_currentOffset), out uint value))
ReportMethodEndInsideInstruction();

uint val = (uint)(_ilBytes[_currentOffset] + (_ilBytes[_currentOffset + 1] << 8) + (_ilBytes[_currentOffset + 2] << 16) + (_ilBytes[_currentOffset + 3] << 24));
_currentOffset += 4;
return val;
_currentOffset += sizeof(uint);
return value;
}

private int ReadILToken()
Expand All @@ -53,8 +53,10 @@ private int ReadILToken()

private ulong ReadILUInt64()
{
ulong value = ReadILUInt32();
value |= (((ulong)ReadILUInt32()) << 32);
if (!BinaryPrimitives.TryReadUInt64LittleEndian(_ilBytes.AsSpan(_currentOffset), out ulong value))
ReportMethodEndInsideInstruction();

_currentOffset += sizeof(ulong);
return value;
}

Expand Down
41 changes: 23 additions & 18 deletions src/coreclr/tools/Common/TypeSystem/IL/Stubs/ILEmitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Buffers.Binary;
using System.Collections.Generic;

using System.Runtime.CompilerServices;
using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;
Expand Down Expand Up @@ -49,23 +50,33 @@ internal int RelativeToAbsoluteOffset(int relativeOffset)

private void EmitByte(byte b)
{
if (_instructions.Length == _length)
Array.Resize<byte>(ref _instructions, 2 * _instructions.Length + 10);
if (_length == _instructions.Length)
Grow();
_instructions[_length++] = b;
}

private void EmitUInt16(ushort value)
{
EmitByte((byte)value);
EmitByte((byte)(value >> 8));
if (_length + sizeof(ushort) > _instructions.Length)
Grow();

BinaryPrimitives.WriteUInt16LittleEndian(_instructions.AsSpan(_length, sizeof(ushort)), value);
_length += sizeof(ushort);
}

private void EmitUInt32(int value)
{
EmitByte((byte)value);
EmitByte((byte)(value >> 8));
EmitByte((byte)(value >> 16));
EmitByte((byte)(value >> 24));
if (_length + sizeof(int) > _instructions.Length)
Grow();

BinaryPrimitives.WriteInt32LittleEndian(_instructions.AsSpan(_length, sizeof(int)), value);
_length += sizeof(int);
}

[MethodImpl(MethodImplOptions.NoInlining)]
private void Grow()
{
Array.Resize(ref _instructions, 2 * _instructions.Length + 10);
}

public void Emit(ILOpcode opcode)
Expand Down Expand Up @@ -468,19 +479,13 @@ internal void PatchLabels()
Debug.Assert(patch.Label.IsPlaced);
Debug.Assert(_startOffsetForLinking != StartOffsetNotSet);

int offset = patch.Offset;
Span<byte> offsetSpan = _instructions.AsSpan(patch.Offset, sizeof(int));

int delta = _instructions[offset + 3] << 24 |
_instructions[offset + 2] << 16 |
_instructions[offset + 1] << 8 |
_instructions[offset];
int delta = BinaryPrimitives.ReadInt32LittleEndian(offsetSpan);

int value = patch.Label.AbsoluteOffset - _startOffsetForLinking - patch.Offset - delta;

_instructions[offset] = (byte)value;
_instructions[offset + 1] = (byte)(value >> 8);
_instructions[offset + 2] = (byte)(value >> 16);
_instructions[offset + 3] = (byte)(value >> 24);
BinaryPrimitives.WriteInt32LittleEndian(offsetSpan, value);
}
}

Expand Down

0 comments on commit 5377b58

Please sign in to comment.