diff --git a/src/coreclr/nativeaot/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs b/src/coreclr/nativeaot/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs index b906a335fe16d..49a5039b373ae 100644 --- a/src/coreclr/nativeaot/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs +++ b/src/coreclr/nativeaot/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs @@ -132,7 +132,7 @@ private static unsafe void InitializeGlobalTablesForModule(TypeManagerHandle typ IntPtr staticsSection = RuntimeImports.RhGetModuleSection(typeManager, ReadyToRunSectionType.GCStaticRegion, out length); if (staticsSection != IntPtr.Zero) { - Debug.Assert(length % IntPtr.Size == 0); + Debug.Assert(length % (MethodTable.SupportsRelativePointers ? sizeof(int) : sizeof(nint)) == 0); object[] spine = InitializeStatics(staticsSection, length); @@ -170,31 +170,39 @@ internal static void RunModuleInitializers() private static unsafe void RunInitializers(TypeManagerHandle typeManager, ReadyToRunSectionType section) { - var initializers = (delegate**)RuntimeImports.RhGetModuleSection(typeManager, section, out int length); - Debug.Assert(length % IntPtr.Size == 0); - int count = length / IntPtr.Size; - for (int i = 0; i < count; i++) + var pInitializers = (byte*)RuntimeImports.RhGetModuleSection(typeManager, section, out int length); + Debug.Assert(length % (MethodTable.SupportsRelativePointers ? sizeof(int) : sizeof(nint)) == 0); + + for (byte* pCurrent = pInitializers; + pCurrent < (pInitializers + length); + pCurrent += MethodTable.SupportsRelativePointers ? sizeof(int) : sizeof(nint)) { - initializers[i](); + var initializer = MethodTable.SupportsRelativePointers ? (delegate*)ReadRelPtr32(pCurrent) : (delegate*)pCurrent; + initializer(); } + + static void* ReadRelPtr32(void* address) + => (byte*)address + *(int*)address; } private static unsafe object[] InitializeStatics(IntPtr gcStaticRegionStart, int length) { - IntPtr gcStaticRegionEnd = (IntPtr)((byte*)gcStaticRegionStart + length); + byte* gcStaticRegionEnd = (byte*)gcStaticRegionStart + length; - object[] spine = new object[length / IntPtr.Size]; + object[] spine = new object[length / (MethodTable.SupportsRelativePointers ? sizeof(int) : sizeof(nint))]; ref object rawSpineData = ref Unsafe.As(ref Unsafe.As(spine).Data); int currentBase = 0; - for (IntPtr** block = (IntPtr**)gcStaticRegionStart; block < (IntPtr**)gcStaticRegionEnd; block++) + for (byte* block = (byte*)gcStaticRegionStart; + block < gcStaticRegionEnd; + block += MethodTable.SupportsRelativePointers ? sizeof(int) : sizeof(nint)) { // Gc Static regions can be shared by modules linked together during compilation. To ensure each // is initialized once, the static region pointer is stored with lowest bit set in the image. // The first time we initialize the static region its pointer is replaced with an object reference // whose lowest bit is no longer set. - IntPtr* pBlock = *block; + IntPtr* pBlock = MethodTable.SupportsRelativePointers ? (IntPtr*)ReadRelPtr32(block) : *(IntPtr**)block; nint blockAddr = MethodTable.SupportsRelativePointers ? (nint)ReadRelPtr32(pBlock) : *pBlock; if ((blockAddr & GCStaticRegionConstants.Uninitialized) == GCStaticRegionConstants.Uninitialized) { diff --git a/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs b/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs index 941d49785454a..ae686b60b039b 100644 --- a/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs +++ b/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs @@ -902,7 +902,10 @@ internal DispatchMap* DispatchMap return DynamicTemplateType->DispatchMap; } - return ((DispatchMap**)TypeManager.DispatchMap)[idxDispatchMap]; + if (SupportsRelativePointers) + return (DispatchMap*)FollowRelativePointer((int*)TypeManager.DispatchMap + idxDispatchMap); + else + return ((DispatchMap**)TypeManager.DispatchMap)[idxDispatchMap]; } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs index 4dd52258d2084..20be29d3e01f5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs @@ -30,8 +30,16 @@ protected internal EmbeddedPointerIndirectionNode(TTarget target) public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { - dataBuilder.RequireInitialPointerAlignment(); - dataBuilder.EmitPointerReloc(Target); + if (factory.Target.SupportsRelativePointers) + { + dataBuilder.RequireInitialAlignment(sizeof(int)); + dataBuilder.EmitReloc(Target, RelocType.IMAGE_REL_BASED_RELPTR32); + } + else + { + dataBuilder.RequireInitialPointerAlignment(); + dataBuilder.EmitPointerReloc(Target); + } } // At minimum, Target needs to be reported as a static dependency by inheritors. diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs index a328dc03ee77f..fe53861e70ca4 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs @@ -141,7 +141,11 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) foreach (var module in sortedModules) { - builder.EmitPointerReloc(factory.MethodEntrypoint(module.GetGlobalModuleType().GetStaticConstructor())); + IMethodNode entrypoint = factory.MethodEntrypoint(module.GetGlobalModuleType().GetStaticConstructor()); + if (factory.Target.SupportsRelativePointers) + builder.EmitReloc(entrypoint, RelocType.IMAGE_REL_BASED_RELPTR32); + else + builder.EmitPointerReloc(entrypoint); } var result = builder.ToObjectData();