Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,31 @@ public static unsafe void WriteValue(RelocType relocType, void* location, long v
}
}

public static unsafe int WriteVariableLengthValue(RelocType relocType, byte* location, long value)
{
Debug.Assert(IsVariableLength(relocType));
switch (relocType)
{
case RelocType.WASM_TYPE_INDEX_LEB:
case RelocType.WASM_GLOBAL_INDEX_LEB:
case RelocType.WASM_FUNCTION_INDEX_LEB:
case RelocType.WASM_MEMORY_ADDR_LEB:
case RelocType.WASM_MEMORY_ADDR_REL_LEB:
case RelocType.WASM_CLR_RESTORE_CONTEXT_EXCEPTION_TAG_LEB:
DwarfHelper.WriteULEB128(new Span<byte>((byte*)location, WASM_PADDED_RELOC_SIZE_32), checked((ulong)value));
return (int)DwarfHelper.SizeOfULEB128((ulong)value);

case RelocType.WASM_TABLE_INDEX_SLEB:
case RelocType.WASM_MEMORY_ADDR_SLEB:
case RelocType.WASM_MEMORY_ADDR_REL_SLEB:
DwarfHelper.WriteSLEB128(new Span<byte>((byte*)location, WASM_PADDED_RELOC_SIZE_32), value);
return (int)DwarfHelper.SizeOfSLEB128(value);
default:
Debug.Fail("Invalid variable-length RelocType: " + relocType);
return 0;
}
}

public static readonly int MaxSize = 8;
// Note: Please update the above field if the max size
// changes when adding a new case to this method.
Expand Down Expand Up @@ -742,6 +767,45 @@ public static int GetSize(RelocType relocType)
};
}

public static bool IsVariableLength(RelocType relocType)
{
return relocType switch
{
RelocType.WASM_FUNCTION_INDEX_LEB or
RelocType.WASM_TABLE_INDEX_SLEB or
RelocType.WASM_TYPE_INDEX_LEB or
RelocType.WASM_GLOBAL_INDEX_LEB or
RelocType.WASM_MEMORY_ADDR_LEB or
RelocType.WASM_MEMORY_ADDR_SLEB or
RelocType.WASM_MEMORY_ADDR_REL_LEB or
RelocType.WASM_MEMORY_ADDR_REL_SLEB or
RelocType.WASM_CLR_RESTORE_CONTEXT_EXCEPTION_TAG_LEB => true,
_ => false,
};
}

public static int ActualSize(RelocType relocType, long resolvedValue)
{
Debug.Assert(IsVariableLength(relocType));
switch (relocType)
{
case RelocType.WASM_FUNCTION_INDEX_LEB:
case RelocType.WASM_TYPE_INDEX_LEB:
case RelocType.WASM_GLOBAL_INDEX_LEB:
case RelocType.WASM_MEMORY_ADDR_LEB:
case RelocType.WASM_MEMORY_ADDR_REL_LEB:
case RelocType.WASM_CLR_RESTORE_CONTEXT_EXCEPTION_TAG_LEB:
return (int)DwarfHelper.SizeOfULEB128((ulong)resolvedValue);
case RelocType.WASM_TABLE_INDEX_SLEB:
case RelocType.WASM_MEMORY_ADDR_SLEB:
case RelocType.WASM_MEMORY_ADDR_REL_SLEB:
return (int)DwarfHelper.SizeOfSLEB128(resolvedValue);
default:
Debug.Fail("Invalid reloc type");
return 0;
}
}

public static unsafe long ReadValue(RelocType relocType, void* location)
{
switch (relocType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

using System;
using System.Buffers;
using System.Diagnostics;
using System.IO;
using System.Numerics;

namespace ILCompiler.ObjectWriter
Expand Down Expand Up @@ -122,6 +124,40 @@ public static ulong ReadULEB128(ReadOnlySpan<byte> buffer, out int bytesRead)
return value;
}

internal static ulong? ReadULEB128(Stream source, out int bytesRead)
{
Debug.Assert(source.CanSeek);
Debug.Assert(source.Length >= 0);

ulong value = 0;
int shift = 0;
bytesRead = 0;

while (true)
{
int b = source.ReadByte();
if (b < 0)
{
if (bytesRead == 0)
{
return null;
}

throw new InvalidDataException("Unexpected end of stream while reading a ULEB128 value.");
}

byte @byte = (byte)b;
bytesRead++;
value |= ((ulong)@byte & 0x7f) << shift;
if ((@byte & 0x80) == 0)
{
return value;
}

shift += 7;
}
}

public static long ReadSLEB128(ReadOnlySpan<byte> buffer) => ReadSLEB128(buffer, out _);

public static long ReadSLEB128(ReadOnlySpan<byte> buffer, out int bytesRead)
Expand Down
Loading
Loading