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 @@ -924,6 +924,8 @@ enum class CorInfoReloc
// e.g. directly loading from or storing to a C++ global.
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 as an offset from __image_base
Comment thread
adamperlin marked this conversation as resolved.
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.
};
Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/jit/emitwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,9 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
case IF_MEMADDR:
{
dst += emitOutputOpcode(dst, ins);
dst += emitOutputConstant(dst, id, SIGNED, CorInfoReloc::WASM_MEMORY_ADDR_SLEB);
// TODO-WASM: The below reloc we're emitting here is specific to R2R and assumes the address we want
// is an offset from __image_base
dst += emitOutputConstant(dst, id, SIGNED, CorInfoReloc::WASM_MEMORY_ADDR_REL_SLEB);
Comment thread
adamperlin marked this conversation as resolved.
break;
}
case IF_FUNCPTR:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ public void EmitReloc(ISymbolNode symbol, RelocType relocType, int delta = 0)
// And add space for the reloc
switch (relocType)
{
case RelocType.WASM_TABLE_INDEX_U32:
case RelocType.WASM_TABLE_INDEX_I32:
case RelocType.IMAGE_REL_BASED_REL32:
case RelocType.IMAGE_REL_BASED_RELPTR32:
Comment thread
adamperlin marked this conversation as resolved.
case RelocType.IMAGE_REL_BASED_ABSOLUTE:
Comment thread
adamperlin marked this conversation as resolved.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ public enum RelocType
// e.g. directly loading from or storing to a C++ global.
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_TYPE_INDEX_LEB = 0x204, // Wasm: a type index encoded as a 5-byte varuint32, e.g. the type immediate in a call_indirect.
WASM_GLOBAL_INDEX_LEB = 0x205, // Wasm: a global index encoded as a 5-byte varuint32, e.g. the index immediate in a get_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
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_TABLE_INDEX_U32 = 0x206, // 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_U64 = 0x207, // Wasm: a table index encoded as a 8-byte uint64, e.g. for storing the "address" of a function into linear memory
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
Comment thread
adamperlin marked this conversation as resolved.

//
// Relocation operators related to TLS access
Expand Down Expand Up @@ -654,8 +657,15 @@ public static unsafe void WriteValue(RelocType relocType, void* location, long v

case RelocType.WASM_TABLE_INDEX_SLEB:
case RelocType.WASM_MEMORY_ADDR_SLEB:
Comment thread
adamperlin marked this conversation as resolved.
case RelocType.WASM_MEMORY_ADDR_REL_SLEB:
DwarfHelper.WritePaddedSLEB128(new Span<byte>((byte*)location, WASM_PADDED_RELOC_SIZE_32), value);
return;
case RelocType.WASM_TABLE_INDEX_I32:
*(uint*)location = checked((uint)value);
return;
case RelocType.WASM_TABLE_INDEX_I64:
*(ulong*)location = checked((ulong)value);
return;

default:
Debug.Fail("Invalid RelocType: " + relocType);
Expand Down Expand Up @@ -696,8 +706,9 @@ 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_TABLE_INDEX_U32 => 4,
RelocType.WASM_TABLE_INDEX_U64 => 8,
RelocType.WASM_MEMORY_ADDR_REL_SLEB => WASM_PADDED_RELOC_SIZE_32,
RelocType.WASM_TABLE_INDEX_I32 => 4,
RelocType.WASM_TABLE_INDEX_I64 => 8,

_ => throw new NotSupportedException(),
};
Expand Down Expand Up @@ -760,8 +771,8 @@ public static unsafe long ReadValue(RelocType relocType, void* location)
return GetRiscV64AuipcCombo((uint*)location, isStype);
case RelocType.WASM_FUNCTION_INDEX_LEB:
case RelocType.WASM_TABLE_INDEX_SLEB:
case RelocType.WASM_TABLE_INDEX_U32:
case RelocType.WASM_TABLE_INDEX_U64:
case RelocType.WASM_TABLE_INDEX_I32:
case RelocType.WASM_TABLE_INDEX_I64:
case RelocType.WASM_TYPE_INDEX_LEB:
case RelocType.WASM_GLOBAL_INDEX_LEB:
// These wasm relocs do not have offsets, just targets
Comment thread
adamperlin marked this conversation as resolved.
Expand All @@ -771,6 +782,7 @@ public static unsafe long ReadValue(RelocType relocType, void* location)
return checked((long)DwarfHelper.ReadULEB128(new ReadOnlySpan<byte>(location, WASM_PADDED_RELOC_SIZE_32)));

case RelocType.WASM_MEMORY_ADDR_SLEB:
case RelocType.WASM_MEMORY_ADDR_REL_SLEB:
return DwarfHelper.ReadSLEB128(new ReadOnlySpan<byte>(location, WASM_PADDED_RELOC_SIZE_32));

default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ public override int Encode(Span<byte> buffer)
break;

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

Expand Down Expand Up @@ -566,7 +566,7 @@ public static WasmExpr Const(long value)
}
public static WasmExpr ConstRVA(ISymbolNode symbolNode)
{
return new WasmLEBConstantReloc(WasmExprKind.I32Const, symbolNode, RelocType.WASM_MEMORY_ADDR_SLEB);
return new WasmLEBConstantReloc(WasmExprKind.I32Const, symbolNode, RelocType.WASM_MEMORY_ADDR_REL_SLEB);
}

public static WasmExpr Add => new WasmBinaryExpr(WasmExprKind.I32Add);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -714,18 +714,18 @@ private unsafe void ResolveRelocations(int sectionIndex, MemoryStream sectionStr
{
byte[] relocScratchBuffer = new byte[Relocation.MaxSize];

WebcilSection? webcilSection = null;
WebcilSection? curSectionAsWebcil = null;
uint webcilVirtualStart = 0;
if (_sections[sectionIndex] is WebcilSection curSection)
{
webcilSection = curSection;
curSectionAsWebcil = curSection;
webcilVirtualStart = curSection.Header.VirtualAddress;
}

// If we have a webcil section, we expect it to have a nonzero section start. This is because for webcil,
// we should have written the webcil header and each of the section headers (always non-zero size) before any
// section contents
Debug.Assert(webcilSection is null || sectionStart != 0);
Debug.Assert(curSectionAsWebcil is null || sectionStart != 0);

foreach (SymbolicRelocation reloc in relocs)
{
Expand All @@ -739,23 +739,22 @@ private unsafe void ResolveRelocations(int sectionIndex, MemoryStream sectionStr

// The virtual address of the relocation we are resolving
uint virtualRelocOffset = 0;
if (curSectionAsWebcil is not null)
{
virtualRelocOffset = webcilVirtualStart + (uint)reloc.Offset;
Debug.Assert(IsWithinSection(virtualRelocOffset, curSectionAsWebcil));
}

// The virtual address of the symbol this relocation refers to
uint virtualSymbolImageOffset = 0;

WebcilSection? symbolWebcilSection = null;

// TODO-Wasm: Enforce the below boolean as an assert once we are emitting proper Wasm code
// relocs for all code containing nodes
// ---> bool betweenWebcilSections = false;
if (webcilSection is not null && _sections[definedSymbol.SectionIndex] is WebcilSection targetSection)
if (_sections[definedSymbol.SectionIndex] is WebcilSection targetSection)
{
// ---> betweenWebcilSections = true;
symbolWebcilSection = targetSection;

virtualRelocOffset = webcilVirtualStart + (uint)reloc.Offset;
Debug.Assert(IsWithinSection(virtualRelocOffset, webcilSection));

virtualSymbolImageOffset = symbolWebcilSection.Header.VirtualAddress + (uint)definedSymbol.Value;
Debug.Assert(IsWithinSection(virtualSymbolImageOffset, symbolWebcilSection));
}
Expand Down Expand Up @@ -811,14 +810,44 @@ private unsafe void ResolveRelocations(int sectionIndex, MemoryStream sectionStr
long fileOffset = symbolWebcilSection.Header.PointerToRawData + definedSymbol.Value;
Relocation.WriteValue(reloc.Type, pData, fileOffset + addend);
break;
case RelocType.WASM_MEMORY_ADDR_SLEB:
case RelocType.WASM_MEMORY_ADDR_REL_SLEB:
{
// WASM-TODO actually implement this
// These relocs should be for cases of the form:
// global.get __image_base
// i32.const <reloc>
// i32.add
// i32.load 0
// 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();
}

Relocation.WriteValue(reloc.Type, pData, virtualSymbolImageOffset + addend);
break;
}
case RelocType.WASM_TABLE_INDEX_U32:
case RelocType.WASM_TABLE_INDEX_I32:
case RelocType.WASM_TABLE_INDEX_I64:
case RelocType.WASM_TABLE_INDEX_SLEB:
Comment thread
adamperlin marked this conversation as resolved.
{
// WASM-TODO actually implement this
string symbolName = reloc.SymbolName.ToString();
int index = _uniqueSymbols[symbolName];
// Here, we are effectively writing a table offset relative to the table_base.
// These will need to be fixed up by the runtime after load by adding __image_function_pointer_base
// TODO-WASM: We need to emit these for fixup with an addend at runtime
Relocation.WriteValue(reloc.Type, pData, index);
break;
}
case RelocType.WASM_FUNCTION_INDEX_LEB:
{
string symbolName = reloc.SymbolName.ToString();
int index = _uniqueSymbols[symbolName];

// These are module-local function pointer indices, so we can simply write out the assigned function index
// for this particular symbol
Relocation.WriteValue(reloc.Type, pData, index);
break;
}
default:
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_TABLE_INDEX_SLEB => RelocType.WASM_TABLE_INDEX_SLEB,
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_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
2 changes: 2 additions & 0 deletions src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,8 @@ public enum CorInfoReloc
// e.g. directly loading from or storing to a C++ global.
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
Comment thread
adamperlin marked this conversation as resolved.
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.
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public override ObjectData GetData(NodeFactory factory, System.Boolean relocsOnl
builder.AddSymbol(this);
WasmTypeNode typeNode;

RelocType tableIndexPointerRelocType = factory.Target.PointerSize == 4 ? RelocType.WASM_TABLE_INDEX_U32 : RelocType.WASM_TABLE_INDEX_U64;
RelocType tableIndexPointerRelocType = factory.Target.PointerSize == 4 ? RelocType.WASM_TABLE_INDEX_I32 : RelocType.WASM_TABLE_INDEX_I64;

if (_import.Signature is GenericLookupSignature)
{
Expand Down
Loading