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
Original file line number Diff line number Diff line change
Expand Up @@ -627,9 +627,9 @@ public static int GetSize(RelocType relocType)
RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L => 4,
RelocType.IMAGE_REL_BASED_THUMB_MOV32 => 8,
RelocType.IMAGE_REL_BASED_THUMB_MOV32_PCREL => 8,
RelocType.IMAGE_REL_BASED_LOONGARCH64_PC => 16,
RelocType.IMAGE_REL_BASED_LOONGARCH64_JIR => 16,
RelocType.IMAGE_REL_BASED_RISCV64_PC => 16,
RelocType.IMAGE_REL_BASED_LOONGARCH64_PC => 8,
RelocType.IMAGE_REL_BASED_LOONGARCH64_JIR => 8,
RelocType.IMAGE_REL_BASED_RISCV64_PC => 8,
_ => throw new NotSupportedException(),
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@ public void EmitLD(Register regDst, Register regSrc, int offset)
Builder.EmitUInt((uint)(0x28c00000 | (uint)((offset & 0xfff) << 10) | ((uint)regSrc << 5) | (uint)regDst));
}

public void EmitLD(Register regDst, ISymbolNode symbol)
{
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_LOONGARCH64_PC);
// pcalau12i reg, off-hi-20bits
EmitPCALAU12I(regDst);

// ld_d reg, reg, off-lo-12bits
EmitLD(regDst, regDst, 0);
}

public void EmitRET()
{
// jirl R0,R1,0
Expand All @@ -107,26 +117,10 @@ public void EmitJMP(ISymbolNode symbol)
{
if (symbol.RepresentsIndirectionCell)
{
Builder.RequireInitialPointerAlignment();

if (Builder.CountBytes % Builder.TargetPointerSize != 0)
{
// Emit a NOP instruction to align the 64-bit reloc below.
EmitNOP();
}

// pcaddi R21, 0
EmitPCADDI(Register.R21);

EmitLD(Register.R21, Register.R21, 0x10);

// ld_d R21, R21, 0
EmitLD(Register.R21, Register.R21, 0);
EmitLD(Register.R21, symbol);

// jirl R0,R21,0
EmitJMP(Register.R21);

Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_DIR64);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ public void EmitJALR(Register regDst, Register regSrc, int offset)
Builder.EmitUInt((uint)(0x00000067u | ((uint)regSrc << 15) | ((uint)regDst << 7) | (uint)((offset & 0xfff) << 20)));
}

public void EmitLD(Register regDst, ISymbolNode symbol)
{
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_RISCV64_PC);
//auipc reg, off-hi-20bits
EmitPC(regDst);
//ld reg, off-lo-12bits(reg)
EmitLD(regDst, regDst, 0);
}

public void EmitRET()
{
// jalr x0,0(x1)
Expand All @@ -103,24 +112,9 @@ public void EmitJMP(ISymbolNode symbol)
{
if (symbol.RepresentsIndirectionCell)
{
Builder.RequireInitialPointerAlignment();

if (Builder.CountBytes % Builder.TargetPointerSize != 0)
{
// Emit a NOP instruction to align the 64-bit reloc below.
EmitNOP();
}

// auipc x29, 0
EmitPC(Register.X29);
// ld x29,16(x29)
EmitLD(Register.X29, Register.X29, 16);
// ld x29,0(x29)
EmitLD(Register.X29, Register.X29, 0);
EmitLD(Register.X29, symbol);
// jalr x0,0(x29)
EmitJALR(Register.X0, Register.X29, 0);

Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_DIR64);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ enum Kind

private readonly ImportSectionNode _containingImportSection;

private readonly int _symbolOffset = 0;

/// <summary>
/// Import thunks are used to call a runtime-provided helper which fixes up an indirection cell in a particular
/// import section. Optionally they may also contain a relocation for a specific indirection cell to fix up.
Expand Down Expand Up @@ -62,21 +60,8 @@ public ImportThunk(NodeFactory factory, ReadyToRunHelper helperId, ImportSection
{
_thunkKind = Kind.Eager;
}

if (_thunkKind != Kind.Eager
&& factory.Target.Architecture is Internal.TypeSystem.TargetArchitecture.LoongArch64
or Internal.TypeSystem.TargetArchitecture.RiscV64)
{
// We stuff the reloc to the module import pointer before the start of the thunk
// to ensure alignment.
// The thunk itself starts immediately after the reloc.
// We don't need this for an Eager thunk.
_symbolOffset = 8;
}
}

int ISymbolNode.Offset => base.Offset + _symbolOffset;

public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append("DelayLoadHelper->"u8);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ protected override void EmitCode(NodeFactory factory, ref ARM64Emitter instructi
instructionEncoder.EmitJMP(_helperCell);
return;
}

if (relocsOnly)
{
// When doing relocs only, we don't need to generate the actual instructions
// as they will be ignored. Just emit the jump so we record the dependency.
// as they will be ignored. Just emit the module import load and jump so we record the dependencies.
instructionEncoder.EmitADRP(Register.X1, factory.ModuleImport);
instructionEncoder.EmitLDR(Register.X1, Register.X1, factory.ModuleImport);
instructionEncoder.EmitJMP(_helperCell);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,11 @@ protected override void EmitCode(NodeFactory factory, ref LoongArch64Emitter ins
instructionEncoder.EmitJMP(_helperCell);
return;
}

instructionEncoder.Builder.RequireInitialPointerAlignment();
Debug.Assert(instructionEncoder.Builder.CountBytes == 0);

instructionEncoder.Builder.EmitReloc(factory.ModuleImport, RelocType.IMAGE_REL_BASED_DIR64);

Debug.Assert(instructionEncoder.Builder.CountBytes == ((ISymbolNode)this).Offset);

if (relocsOnly)
{
// When doing relocs only, we don't need to generate the actual instructions
// as they will be ignored. Just emit the jump so we record the dependency.
// as they will be ignored. Just emit the module import load and jump so we record the dependencies.
instructionEncoder.EmitLD(Register.R5, factory.ModuleImport);
instructionEncoder.EmitJMP(_helperCell);
return;
}
Expand All @@ -50,32 +43,13 @@ protected override void EmitCode(NodeFactory factory, ref LoongArch64Emitter ins
int index = _containingImportSection.IndexFromBeginningOfArray;
instructionEncoder.EmitMOV(Register.R12, checked((ushort)index));

int offset = -instructionEncoder.Builder.CountBytes;

// get pc
// pcaddi T1=R13, 0
instructionEncoder.EmitPCADDI(Register.R13);

// load Module* -> T1
instructionEncoder.EmitLD(Register.R13, Register.R13, offset);

// ld_d R13, R13, 0
instructionEncoder.EmitLD(Register.R13, Register.R13, 0);
instructionEncoder.EmitLD(Register.R13, factory.ModuleImport);
break;
}

case Kind.Lazy:
{
int offset = -instructionEncoder.Builder.CountBytes;
// get pc
// pcaddi R5, 0
instructionEncoder.EmitPCADDI(Register.R5);

// load Module* -> R5=A1
instructionEncoder.EmitLD(Register.R5, Register.R5, offset);

// ld_d R5, R5, 0
instructionEncoder.EmitLD(Register.R5, Register.R5, 0);
instructionEncoder.EmitLD(Register.R5, factory.ModuleImport);
break;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,11 @@ protected override void EmitCode(NodeFactory factory, ref RiscV64Emitter instruc
return;
}

instructionEncoder.Builder.RequireInitialPointerAlignment();
Debug.Assert(instructionEncoder.Builder.CountBytes == 0);

instructionEncoder.Builder.EmitReloc(factory.ModuleImport, RelocType.IMAGE_REL_BASED_DIR64);

Debug.Assert(instructionEncoder.Builder.CountBytes == ((ISymbolNode)this).Offset);

if (relocsOnly)
{
// When doing relocs only, we don't need to generate the actual instructions
// as they will be ignored. Just emit the jump so we record the dependency.
// as they will be ignored. Just emit the module import load and jump so we record the dependencies.
instructionEncoder.EmitLD(Register.X11, factory.ModuleImport);
instructionEncoder.EmitJMP(_helperCell);
return;
}
Expand All @@ -51,31 +45,15 @@ protected override void EmitCode(NodeFactory factory, ref RiscV64Emitter instruc
int index = _containingImportSection.IndexFromBeginningOfArray;
instructionEncoder.EmitLI(Register.X5, index);

int offset = -instructionEncoder.Builder.CountBytes;

// get pc
// auipc t1, 0
instructionEncoder.EmitPC(Register.X6);
// Move Module* -> t1
instructionEncoder.EmitLD(Register.X6, factory.ModuleImport);

// load Module* -> t1
instructionEncoder.EmitLD(Register.X6, Register.X6, offset);

// ld t1, t1, 0
instructionEncoder.EmitLD(Register.X6, Register.X6, 0);
break;
}
case Kind.Lazy:
{
int offset = -instructionEncoder.Builder.CountBytes;

// get pc
instructionEncoder.EmitPC(Register.X11);

// load Module* -> a1
instructionEncoder.EmitLD(Register.X11, Register.X11, offset);

// ld a1, a1, 0
instructionEncoder.EmitLD(Register.X11, Register.X11, 0);
// Load Module* -> a1
instructionEncoder.EmitLD(Register.X11, factory.ModuleImport);
break;
}
default:
Expand Down
Loading