Skip to content
Draft
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 @@ -193,9 +193,15 @@ public void EmitMOV(Register destination, ISymbolNode symbol)

// b.w symbol
public void EmitJMP(ISymbolNode symbol)
{
EmitJMP(symbol, 0);
}

// b.w symbol with addend
public void EmitJMP(ISymbolNode symbol, int addend)
{
Debug.Assert(!symbol.RepresentsIndirectionCell);
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_THUMB_BRANCH24);
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_THUMB_BRANCH24, addend);
Builder.EmitByte(0);
Builder.EmitByte(0xF0);
Builder.EmitByte(0);
Expand Down
24 changes: 3 additions & 21 deletions src/coreclr/tools/Common/Compiler/ObjectWriter/ObjectWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,20 +152,6 @@ or IMAGE_REL_BASED_THUMB_BRANCH24 or IMAGE_REL_BASED_THUMB_MOV32_PCREL &&
// Resolve the relocation to already defined symbol and write it into data
fixed (byte *pData = data)
{
// RyuJIT generates the Thumb bit in the addend and we also get it from
// the symbol value. The AAELF ABI specification defines the R_ARM_THM_JUMP24
// and R_ARM_THM_MOVW_PREL_NC relocations using the formula ((S + A) | T) – P.
// The thumb bit is thus supposed to be only added once.
// For R_ARM_THM_JUMP24 the thumb bit cannot be encoded, so mask it out.
//
// R2R doesn't use add the thumb bit to the symbol value, so we don't need to do this here.
#if !READYTORUN
long maskThumbBitOut = relocType is IMAGE_REL_BASED_THUMB_BRANCH24 or IMAGE_REL_BASED_THUMB_MOV32_PCREL ? 1 : 0;
long maskThumbBitIn = relocType is IMAGE_REL_BASED_THUMB_MOV32_PCREL ? 1 : 0;
#else
long maskThumbBitOut = 0;
long maskThumbBitIn = 0;
#endif
long adjustedAddend = addend;

adjustedAddend -= relocType switch
Expand All @@ -176,9 +162,8 @@ or IMAGE_REL_BASED_THUMB_BRANCH24 or IMAGE_REL_BASED_THUMB_MOV32_PCREL &&
_ => 0
};

adjustedAddend += definedSymbol.Value & ~maskThumbBitOut;
adjustedAddend += definedSymbol.Value;
adjustedAddend += Relocation.ReadValue(relocType, (void*)pData);
adjustedAddend |= definedSymbol.Value & maskThumbBitIn;
adjustedAddend -= offset;

if (relocType is IMAGE_REL_BASED_THUMB_BRANCH24 && !Relocation.FitsInThumb2BlRel24((int)adjustedAddend))
Expand Down Expand Up @@ -387,18 +372,15 @@ public void EmitObject(Stream outputFileStream, IReadOnlyCollection<DependencyNo
bool isMethod = node is IMethodBodyNode or AssemblyStubNode;
#if !READYTORUN
bool recordSize = isMethod;
long thumbBit = _nodeFactory.Target.Architecture == TargetArchitecture.ARM && isMethod ? 1 : 0;
#else
bool recordSize = true;
// R2R records the thumb bit in the addend when needed, so we don't have to do it here.
long thumbBit = 0;
#endif
foreach (ISymbolDefinitionNode n in nodeContents.DefinedSymbols)
{
string mangledName = n == node ? currentSymbolName : GetMangledName(n);
sectionWriter.EmitSymbolDefinition(
mangledName,
n.Offset + thumbBit,
n.Offset,
n.Offset == 0 && recordSize ? nodeContents.Data.Length : 0);

_outputInfoBuilder?.AddSymbol(new OutputSymbol(sectionWriter.SectionIndex, (ulong)(sectionWriter.Position + n.Offset), mangledName));
Expand All @@ -408,7 +390,7 @@ public void EmitObject(Stream outputFileStream, IReadOnlyCollection<DependencyNo
string alternateCName = ExternCName(alternateName);
sectionWriter.EmitSymbolDefinition(
alternateCName,
n.Offset + thumbBit,
n.Offset,
n.Offset == 0 && recordSize ? nodeContents.Data.Length : 0,
global: !isHidden);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1079,9 +1079,9 @@ private void OutputFinalizerMethod(NodeFactory factory, ref ObjectDataBuilder ob
MethodDesc finalizerMethod = _type.GetFinalizer();
MethodDesc canonFinalizerMethod = finalizerMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
if (factory.Target.SupportsRelativePointers)
objData.EmitReloc(factory.MethodEntrypoint(canonFinalizerMethod), RelocType.IMAGE_REL_BASED_RELPTR32);
objData.EmitReloc(factory.MethodEntrypoint(canonFinalizerMethod), RelocType.IMAGE_REL_BASED_RELPTR32, factory.Target.CodeDelta);
else
objData.EmitPointerReloc(factory.MethodEntrypoint(canonFinalizerMethod));
objData.EmitPointerReloc(factory.MethodEntrypoint(canonFinalizerMethod), factory.Target.CodeDelta);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo
ISymbolNode target = _isAddressTaken
? factory.AddressTakenMethodEntrypoint(canonMethod, _isUnboxingStub)
: factory.MethodEntrypoint(canonMethod, _isUnboxingStub);
builder.EmitPointerReloc(target);
builder.EmitPointerReloc(target, factory.Target.CodeDelta);

// Find out what's the context to use
ISortableSymbolNode contextParameter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
IMethodNode entrypoint = factory.MethodEntrypoint(module.GetGlobalModuleType().GetStaticConstructor());
if (factory.Target.SupportsRelativePointers)
builder.EmitReloc(entrypoint, RelocType.IMAGE_REL_BASED_RELPTR32);
builder.EmitReloc(entrypoint, RelocType.IMAGE_REL_BASED_RELPTR32, factory.Target.CodeDelta);
else
builder.EmitPointerReloc(entrypoint);
builder.EmitPointerReloc(entrypoint, factory.Target.CodeDelta);
}

var result = builder.ToObjectData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo
{
// Emit pointer to the cctor
MethodDesc cctorMethod = _type.GetStaticConstructor();
builder.EmitPointerReloc(factory.ExactCallableAddress(cctorMethod));
builder.EmitPointerReloc(factory.ExactCallableAddress(cctorMethod), factory.Target.CodeDelta);
}
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
}

objData.EmitByte(commandReservation, command);
objData.EmitReloc(factory.MethodEntrypoint(entry.Method), RelocType.IMAGE_REL_BASED_RELPTR32);
objData.EmitReloc(factory.MethodEntrypoint(entry.Method), RelocType.IMAGE_REL_BASED_RELPTR32, factory.Target.CodeDelta);
}

_size = objData.CountBytes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bo
{
if (!_target.RepresentsIndirectionCell)
{
encoder.EmitJMP(_target); // b methodEntryPoint
encoder.EmitJMP(_target, factory.Target.CodeDelta); // b methodEntryPoint
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ protected void EmitDictionaryLookup(NodeFactory factory, ref ARMEmitter encoder,
{
encoder.EmitCMP(result, 0);
encoder.EmitRETIfNotEqual();
encoder.EmitJMP(GetBadSlotHelper(factory));
encoder.EmitJMP(GetBadSlotHelper(factory), factory.Target.CodeDelta);
}
}

Expand Down Expand Up @@ -83,7 +83,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter enco

encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result);
encoder.EmitSUB(encoder.TargetRegister.Arg0, (byte)cctorContextSize);
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase));
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase), factory.Target.CodeDelta);
}
}
break;
Expand Down Expand Up @@ -116,7 +116,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter enco
encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result);
encoder.EmitMOV(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg2);
encoder.EmitSUB(encoder.TargetRegister.Arg0, cctorContextSize);
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase));
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase), factory.Target.CodeDelta);
}
}
break;
Expand Down Expand Up @@ -155,7 +155,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter enco
// Second arg: index of the type in the ThreadStatic section of the modules
encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg1, factory.Target.PointerSize);

encoder.EmitJMP(helperEntrypoint);
encoder.EmitJMP(helperEntrypoint, factory.Target.CodeDelta);
}
break;

Expand All @@ -182,7 +182,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter enco
Debug.Assert(target.Constructor.Method.Signature.Length == 2);
}

encoder.EmitJMP(target.Constructor);
encoder.EmitJMP(target.Constructor, factory.Target.CodeDelta);
}
break;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bo
encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol(target));
encoder.EmitMOV(encoder.TargetRegister.Arg0/*Result*/, encoder.TargetRegister.Arg1);
encoder.EmitSUB(encoder.TargetRegister.Arg0, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target));
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase));
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase), factory.Target.CodeDelta);
}
}
break;
Expand All @@ -53,14 +53,14 @@ protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bo

if (!factory.PreinitializationManager.HasLazyStaticConstructor(target))
{
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.GetThreadStaticBaseForType));
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.GetThreadStaticBaseForType), factory.Target.CodeDelta);
}
else
{
encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target));
encoder.EmitSUB(encoder.TargetRegister.Arg2, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target));
// TODO: performance optimization - inline the check verifying whether we need to trigger the cctor
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase));
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase), factory.Target.CodeDelta);
}
}
break;
Expand All @@ -80,7 +80,7 @@ protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bo
encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result);
encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target));
encoder.EmitSUB(encoder.TargetRegister.Arg0, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target));
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase));
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase), factory.Target.CodeDelta);
}
}
break;
Expand Down Expand Up @@ -118,7 +118,7 @@ protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bo
Debug.Assert(target.Constructor.Method.Signature.Length == 2);
}

encoder.EmitJMP(target.Constructor);
encoder.EmitJMP(target.Constructor, factory.Target.CodeDelta);
}
break;

Expand All @@ -128,7 +128,7 @@ protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bo
if (targetMethod.OwningType.IsInterface)
{
encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.InterfaceDispatchCell(targetMethod));
encoder.EmitJMP(factory.ExternFunctionSymbol("RhpResolveInterfaceMethod"));
encoder.EmitJMP(factory.ExternFunctionSymbol("RhpResolveInterfaceMethod"), factory.Target.CodeDelta);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public partial class TentativeMethodNode
{
protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly)
{
encoder.EmitJMP(GetTarget(factory));
encoder.EmitJMP(GetTarget(factory), factory.Target.CodeDelta);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public partial class UnboxingStubNode
protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly)
{
encoder.EmitADD(encoder.TargetRegister.Arg0, (byte)factory.Target.PointerSize); // add r0, sizeof(void*);
encoder.EmitJMP(GetUnderlyingMethodEntrypoint(factory)); // b methodEntryPoint
encoder.EmitJMP(GetUnderlyingMethodEntrypoint(factory), factory.Target.CodeDelta); // b methodEntryPoint
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2642,7 +2642,7 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f
if (method is null)
builder.EmitZeroPointer();
else
builder.EmitPointerReloc(factory.ExactCallableAddressTakenAddress(method, isUnboxingStub: false));
builder.EmitPointerReloc(factory.ExactCallableAddressTakenAddress(method, isUnboxingStub: false), factory.Target.CodeDelta);
}
}

Expand Down
Loading