Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,8 @@ enum class CorInfoReloc
// e.g. in R2R scenarios as an offset from __image_base
WASM_TYPE_INDEX_LEB, // Wasm: a type index encoded as a 5-byte varuint32, e.g. the type immediate in a call_indirect.
WASM_GLOBAL_INDEX_LEB, // Wasm: a global index encoded as a 5-byte varuint32, e.g. the index immediate in a get_global.
WASM_MEMORY_ADDR_REL_LEB, // Wasm: a relative linear memory index encoded as a 5-byte varuint32. Used as the immediate argument of a load or store instruction,
// e.g. in R2R scenarios as an offset from __image_base
};

enum CorInfoGCType
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@

#include <minipal/guid.h>

constexpr GUID JITEEVersionIdentifier = { /* d4aa533f-231b-4bd3-9d4e-238f88b337cb */
0xd4aa533f,
0x231b,
0x4bd3,
{0x9d, 0x4e, 0x23, 0x8f, 0x88, 0xb3, 0x37, 0xcb}
constexpr GUID JITEEVersionIdentifier = { /* 5fad64ab-f0ea-4c4d-b67a-b3a47ef0b321 */
0x5fad64ab,
0xf0ea,
0x4c4d,
{0xb6, 0x7a, 0xb3, 0xa4, 0x7e, 0xf0, 0xb3, 0x21}
};

#endif // JIT_EE_VERSIONING_GUID_H
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,15 @@ public enum RelocType
WASM_MEMORY_ADDR_SLEB = 0x203, // Wasm: a linear memory index encoded as a 5-byte varint32. Used for the immediate argument of a i32.const instruction,
// e.g. taking the address of a C++ global.
WASM_MEMORY_ADDR_REL_SLEB = 0x204, // Wasm: a relative linear memory index encoded as a 5-byte varint32. Used as the immediate argument of an i32.const instruction,
// e.g. in R2R scenarios, encoding an offset from __image_base
// e.g. in R2R scenarios, encoding an offset from $imageBase
WASM_TYPE_INDEX_LEB = 0x205, // Wasm: a type index encoded as a 5-byte varuint32, e.g. the type immediate in a call_indirect.

WASM_GLOBAL_INDEX_LEB = 0x206, // Wasm: a global index encoded as a 5-byte varuint32, e.g. the index immediate in a get_global.

WASM_TABLE_INDEX_I32 = 0x207, // Wasm: a table index encoded as a 4-byte uint32, e.g. for storing the "address" of a function into linear memory
WASM_TABLE_INDEX_I64 = 0x208, // Wasm: a table index encoded as a 8-byte uint64, e.g. for storing the "address" of a function into linear memory
WASM_MEMORY_ADDR_REL_LEB = 0x209, // Wasm: a relative linear memory index encoded as a 5-byte varuint32. Used as the immediate argument of a load or store instruction,
// e.g. in R2R scenarios as an offset from $imageBase

//
// Relocation operators related to TLS access
Expand Down Expand Up @@ -656,6 +658,7 @@ public static unsafe void WriteValue(RelocType relocType, void* location, long v
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:
DwarfHelper.WritePaddedULEB128(new Span<byte>((byte*)location, WASM_PADDED_RELOC_SIZE_32), checked((ulong)value));
return;

Expand Down Expand Up @@ -710,6 +713,7 @@ public static int GetSize(RelocType relocType)
RelocType.WASM_GLOBAL_INDEX_LEB => WASM_PADDED_RELOC_SIZE_32,
RelocType.WASM_MEMORY_ADDR_LEB => WASM_PADDED_RELOC_SIZE_32,
RelocType.WASM_MEMORY_ADDR_SLEB => WASM_PADDED_RELOC_SIZE_32,
RelocType.WASM_MEMORY_ADDR_REL_LEB => WASM_PADDED_RELOC_SIZE_32,
RelocType.WASM_MEMORY_ADDR_REL_SLEB => WASM_PADDED_RELOC_SIZE_32,
RelocType.WASM_TABLE_INDEX_I32 => 4,
RelocType.WASM_TABLE_INDEX_I64 => 8,
Expand Down Expand Up @@ -783,6 +787,7 @@ public static unsafe long ReadValue(RelocType relocType, void* location)
return 0;

case RelocType.WASM_MEMORY_ADDR_LEB:
case RelocType.WASM_MEMORY_ADDR_REL_LEB:
return checked((long)DwarfHelper.ReadULEB128(new ReadOnlySpan<byte>(location, WASM_PADDED_RELOC_SIZE_32)));

case RelocType.WASM_MEMORY_ADDR_SLEB:
Expand Down
146 changes: 103 additions & 43 deletions src/coreclr/tools/Common/Compiler/ObjectWriter/WasmInstructions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,12 +295,82 @@ public static void OffsetRelocationsByOffset(Span<Relocation> buffer, int offset
}
}

class WasmMemoryArgInstruction : WasmExpr
readonly struct WasmEncodableULong : IWasmEncodable
{
private readonly ulong _value;
public WasmEncodableULong(ulong value)
{
_value = value;
}
public int EncodeSize()
{
return (int)DwarfHelper.SizeOfULEB128(_value);
}
public int Encode(Span<byte> buffer)
{
return DwarfHelper.WriteULEB128(buffer, _value);
}
public int EncodeRelocationCount() => 0;
public int EncodeRelocations(Span<Relocation> buffer) => 0;
}

readonly struct WasmEncodableSymbol : IWasmEncodable
{
private readonly ISymbolNode _symbol;
private readonly RelocType _relocType;

public WasmEncodableSymbol(ISymbolNode symbol, RelocType relocType)
{
_symbol = symbol;
_relocType = relocType;
}

public int EncodeSize()
{
return Relocation.GetSize(_relocType);
}

public int Encode(Span<byte> buffer)
{
// The actual value is not encoded into the buffer, instead a relocation is emitted for the symbol
int relocSize = Relocation.GetSize(_relocType);
Debug.Assert(buffer.Length >= relocSize);
switch (_relocType)
{
case RelocType.WASM_FUNCTION_INDEX_LEB:
case RelocType.WASM_MEMORY_ADDR_LEB:
case RelocType.WASM_MEMORY_ADDR_REL_LEB:
case RelocType.WASM_TYPE_INDEX_LEB:
case RelocType.WASM_GLOBAL_INDEX_LEB:
DwarfHelper.WritePaddedULEB128(buffer.Slice(0, relocSize), 0);
break;

case RelocType.WASM_TABLE_INDEX_SLEB:
case RelocType.WASM_MEMORY_ADDR_REL_SLEB:
DwarfHelper.WritePaddedSLEB128(buffer.Slice(0, relocSize), 0);
break;
Comment thread
adamperlin marked this conversation as resolved.

default:
throw new Exception($"Unknown WASM reloc type : {_relocType}");
}
return relocSize;
}

public int EncodeRelocationCount() => 1;

public int EncodeRelocations(Span<Relocation> buffer)
{
buffer[0] = new Relocation(_relocType, 0, _symbol);
return 1;
}
}

class WasmMemoryArgInstruction<TOffset> : WasmExpr where TOffset : IWasmEncodable
{
readonly uint _align;
readonly ulong _offset;
readonly TOffset _offset;

public WasmMemoryArgInstruction(WasmExprKind kind, uint align, ulong offset) : base(kind)
public WasmMemoryArgInstruction(WasmExprKind kind, uint align, TOffset offset) : base(kind)
{
switch (align)
{
Expand All @@ -317,17 +387,25 @@ public WasmMemoryArgInstruction(WasmExprKind kind, uint align, ulong offset) : b

public override int EncodeSize()
{
uint valSize = DwarfHelper.SizeOfULEB128(_align) + DwarfHelper.SizeOfULEB128(_offset);
int valSize = (int)DwarfHelper.SizeOfULEB128(_align) + _offset.EncodeSize();
return base.EncodeSize() + (int)valSize;
}

public override int Encode(Span<byte> buffer)
{
int pos = base.Encode(buffer);
pos += DwarfHelper.WriteULEB128(buffer.Slice(pos), _align);
pos += DwarfHelper.WriteULEB128(buffer.Slice(pos), _offset);
pos += _offset.Encode(buffer.Slice(pos));
return pos;
}
public override int EncodeRelocationCount() => _offset.EncodeRelocationCount();
public override int EncodeRelocations(Span<Relocation> buffer)
{
int relocsEncoded = _offset.EncodeRelocations(buffer);
if (relocsEncoded > 0)
WasmExpr.OffsetRelocationsByOffset(buffer.Slice(0, relocsEncoded), base.EncodeSize() + (int)DwarfHelper.SizeOfULEB128(_align));
return relocsEncoded;
}
}

// Represents a constant expression (e.g., (i32.const <value>))
Expand Down Expand Up @@ -399,46 +477,27 @@ public override int EncodeRelocations(Span<Relocation> buffer)

sealed class WasmLEBConstantReloc : WasmExpr
{
readonly ISymbolNode _symbol;
readonly RelocType _relocType;
readonly WasmEncodableSymbol _symbol;

public WasmLEBConstantReloc(WasmExprKind kind, ISymbolNode symbol, RelocType relocType) : base(kind)
{
_symbol = symbol;
_relocType = relocType;
_symbol = new WasmEncodableSymbol(symbol, relocType);
}
public override int EncodeSize() => base.EncodeSize() + Relocation.GetSize(_relocType);
public override int EncodeSize() => base.EncodeSize() + _symbol.EncodeSize();
public override int Encode(Span<byte> buffer)
{
int pos = base.Encode(buffer);
int relocSize = Relocation.GetSize(_relocType);
switch (_relocType)
{
case RelocType.WASM_FUNCTION_INDEX_LEB:
case RelocType.WASM_MEMORY_ADDR_LEB:
case RelocType.WASM_TYPE_INDEX_LEB:
case RelocType.WASM_GLOBAL_INDEX_LEB:
DwarfHelper.WritePaddedULEB128(buffer.Slice(pos, relocSize), 0);
break;

case RelocType.WASM_TABLE_INDEX_SLEB:
case RelocType.WASM_MEMORY_ADDR_REL_SLEB:
DwarfHelper.WritePaddedSLEB128(buffer.Slice(pos, relocSize), 0);
break;

default:
throw new Exception($"Unknown WASM reloc type : {_relocType}");
}

pos += relocSize;
pos += _symbol.Encode(buffer.Slice(pos));
return pos;
}

public override int EncodeRelocationCount() => 1;
public override int EncodeRelocationCount() => _symbol.EncodeRelocationCount();
public override int EncodeRelocations(Span<Relocation> buffer)
{
buffer[0] = new Relocation(_relocType, base.EncodeSize(), _symbol);
return 1;
int relocsEncoded = _symbol.EncodeRelocations(buffer);
if (relocsEncoded > 0)
WasmExpr.OffsetRelocationsByOffset(buffer.Slice(0, relocsEncoded), base.EncodeSize());
return relocsEncoded;
}
}

Expand Down Expand Up @@ -694,32 +753,33 @@ public static WasmExpr ConstRVA(ISymbolNode symbolNode)
public static WasmExpr Add => new WasmBinaryExpr(WasmExprKind.I32Add);
public static WasmExpr Sub => new WasmBinaryExpr(WasmExprKind.I32Sub);
public static WasmExpr Ge_s => new WasmBinaryExpr(WasmExprKind.I32Ge_s);
public static WasmExpr Load(ulong offset) => new WasmMemoryArgInstruction(WasmExprKind.I32Load, 4, offset);
public static WasmExpr Store(ulong offset) => new WasmMemoryArgInstruction(WasmExprKind.I32Store, 4, offset);
public static WasmExpr Load(ulong offset) => new WasmMemoryArgInstruction<WasmEncodableULong>(WasmExprKind.I32Load, 4, new WasmEncodableULong(offset));
public static WasmExpr LoadWithRVAOffset(ISymbolNode symbolNode) => new WasmMemoryArgInstruction<WasmEncodableSymbol>(WasmExprKind.I32Load, 4, new WasmEncodableSymbol(symbolNode, RelocType.WASM_MEMORY_ADDR_REL_LEB));
public static WasmExpr Store(ulong offset) => new WasmMemoryArgInstruction<WasmEncodableULong>(WasmExprKind.I32Store, 4, new WasmEncodableULong(offset));
}

static class I64
{
public static WasmExpr Load(ulong offset) => new WasmMemoryArgInstruction(WasmExprKind.I64Load, 8, offset);
public static WasmExpr Store(ulong offset) => new WasmMemoryArgInstruction(WasmExprKind.I64Store, 8, offset);
public static WasmExpr Load(ulong offset) => new WasmMemoryArgInstruction<WasmEncodableULong>(WasmExprKind.I64Load, 8, new WasmEncodableULong(offset));
public static WasmExpr Store(ulong offset) => new WasmMemoryArgInstruction<WasmEncodableULong>(WasmExprKind.I64Store, 8, new WasmEncodableULong(offset));
}

static class F32
{
public static WasmExpr Load(ulong offset) => new WasmMemoryArgInstruction(WasmExprKind.F32Load, 4, offset);
public static WasmExpr Store(ulong offset) => new WasmMemoryArgInstruction(WasmExprKind.F32Store, 4, offset);
public static WasmExpr Load(ulong offset) => new WasmMemoryArgInstruction<WasmEncodableULong>(WasmExprKind.F32Load, 4, new WasmEncodableULong(offset));
public static WasmExpr Store(ulong offset) => new WasmMemoryArgInstruction<WasmEncodableULong>(WasmExprKind.F32Store, 4, new WasmEncodableULong(offset));
}

static class F64
{
public static WasmExpr Load(ulong offset) => new WasmMemoryArgInstruction(WasmExprKind.F64Load, 8, offset);
public static WasmExpr Store(ulong offset) => new WasmMemoryArgInstruction(WasmExprKind.F64Store, 8, offset);
public static WasmExpr Load(ulong offset) => new WasmMemoryArgInstruction<WasmEncodableULong>(WasmExprKind.F64Load, 8, new WasmEncodableULong(offset));
public static WasmExpr Store(ulong offset) => new WasmMemoryArgInstruction<WasmEncodableULong>(WasmExprKind.F64Store, 8, new WasmEncodableULong(offset));
}

static class V128
{
public static WasmExpr Load(ulong offset) => new WasmMemoryArgInstruction(WasmExprKind.V128Load, 16, offset);
public static WasmExpr Store(ulong offset) => new WasmMemoryArgInstruction(WasmExprKind.V128Store, 16, offset);
public static WasmExpr Load(ulong offset) => new WasmMemoryArgInstruction<WasmEncodableULong>(WasmExprKind.V128Load, 16, new WasmEncodableULong(offset));
public static WasmExpr Store(ulong offset) => new WasmMemoryArgInstruction<WasmEncodableULong>(WasmExprKind.V128Store, 16, new WasmEncodableULong(offset));
}

static class Memory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ private unsafe void ResolveRelocations(int sectionIndex, MemoryStream sectionStr
case RelocType.WASM_MEMORY_ADDR_REL_SLEB:
{
// These relocs should be for cases of the form:
// global.get __image_base
// global.get $imageBase
// i32.const <reloc>
// i32.add
// i32.load 0
Expand All @@ -961,6 +961,22 @@ private unsafe void ResolveRelocations(int sectionIndex, MemoryStream sectionStr
Relocation.WriteValue(reloc.Type, pData, virtualSymbolImageOffset + addend);
break;
}
case RelocType.WASM_MEMORY_ADDR_REL_LEB:
{
// These relocs should be for cases of the form:
// global.get $imageBase
// i32.load <reloc>
// So, the relocated address value should always represent an offset relative to image base.
// This offset should ALWAYS be equal to the actual offset from image base at runtime, due to Webcil's
// flag mapping
if (symbolWebcilSection is null)
{
throw new InvalidDataException();
}
Comment thread
adamperlin marked this conversation as resolved.

Relocation.WriteValue(reloc.Type, pData, virtualSymbolImageOffset + addend);
break;
}
case RelocType.WASM_TABLE_INDEX_I32:
case RelocType.WASM_TABLE_INDEX_I64:
case RelocType.WASM_TABLE_INDEX_SLEB:
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4250,6 +4250,7 @@ private RelocType GetRelocType(CorInfoReloc reloc)
CorInfoReloc.WASM_MEMORY_ADDR_LEB => RelocType.WASM_MEMORY_ADDR_LEB,
CorInfoReloc.WASM_MEMORY_ADDR_SLEB => RelocType.WASM_MEMORY_ADDR_SLEB,
CorInfoReloc.WASM_MEMORY_ADDR_REL_SLEB => RelocType.WASM_MEMORY_ADDR_REL_SLEB,
CorInfoReloc.WASM_MEMORY_ADDR_REL_LEB => RelocType.WASM_MEMORY_ADDR_REL_LEB,
CorInfoReloc.WASM_TYPE_INDEX_LEB => RelocType.WASM_TYPE_INDEX_LEB,
CorInfoReloc.WASM_GLOBAL_INDEX_LEB => RelocType.WASM_GLOBAL_INDEX_LEB,
_ => throw new ArgumentException("Unsupported relocation type: " + reloc),
Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -515,9 +515,11 @@ public enum CorInfoReloc
WASM_MEMORY_ADDR_SLEB, // Wasm: a linear memory index encoded as a 5-byte varint32. Used for the immediate argument of a i32.const instruction,
// e.g. taking the address of a C++ global.
WASM_MEMORY_ADDR_REL_SLEB, // Wasm: a relative linear memory index encoded as a 5-byte varint32. Used as the immediate argument of an i32.const instruction,
// e.g. in R2R scenarios, encoding an offset from __image_base
// e.g. in R2R scenarios, encoding an offset from $imageBase
WASM_TYPE_INDEX_LEB, // Wasm: a type index encoded as a 5-byte varuint32, e.g. the type immediate in a call_indirect.
WASM_GLOBAL_INDEX_LEB, // Wasm: a global index encoded as a 5-byte varuint32, e.g. the index immediate in a get_global.
WASM_MEMORY_ADDR_REL_LEB, // Wasm: a relative linear memory index encoded as a 5-byte varuint32. Used as the immediate argument of a load or store instruction,
// e.g. in R2R scenarios, encoding an offset from $imageBase
}

public enum CorInfoGCType
Expand Down
Loading