protected void EmitDictionaryLookup(NodeFactory factory, ref ARMEmitter encoder, Register context, Register result, GenericLookupResult lookup, bool relocsOnly) { // INVARIANT: must not trash context register // Find the generic dictionary slot int dictionarySlot = 0; if (!relocsOnly) { // The concrete slot won't be known until we're emitting data - don't ask for it in relocsOnly. dictionarySlot = factory.GenericDictionaryLayout(_dictionaryOwner).GetSlotForEntry(lookup); } // Load the generic dictionary cell encoder.EmitLDR(result, context, dictionarySlot * factory.Target.PointerSize); switch (lookup.LookupResultReferenceType(factory)) { case GenericLookupResultReferenceType.Indirect: // Do another indirection encoder.EmitLDR(result, result); break; case GenericLookupResultReferenceType.ConditionalIndirect: // Test result, 0x1 // JEQ L1 // mov result, [result-1] // L1: throw new NotImplementedException(); default: break; } }
public static void EmitHelperNYIAssert(NodeFactory factory, ref ARMEmitter encoder, ReadyToRunHelperId hId, [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = null, [System.Runtime.CompilerServices.CallerMemberName] string memberName = null, [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) { EmitNYIAssert(factory, ref encoder, hId.ToString() + " is not implemented", sourceFilePath, memberName, sourceLineNumber); }
protected Register GetContextRegister(ref /* readonly */ ARMEmitter encoder) { if (_id == ReadyToRunHelperId.DelegateCtor) { return(encoder.TargetRegister.Arg2); } else { return(encoder.TargetRegister.Arg0); } }
public static void EmitNYIAssert(NodeFactory factory, ref ARMEmitter encoder, string message, [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = null, [System.Runtime.CompilerServices.CallerMemberName] string memberName = null, [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) { ISymbolNode NYI_Assert = factory.ExternSymbol("NYI_Assert"); String CallInfoPrefix = " " + sourceFilePath + "(" + sourceLineNumber.ToString() + "): method " + memberName + ": "; ISymbolNode messageSymbol = factory.ConstantUtf8String(CallInfoPrefix + message); encoder.EmitMOV(encoder.TargetRegister.Arg0, messageSymbol); encoder.EmitJMP(NYI_Assert); }
protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) { if (!_target.RepresentsIndirectionCell) { encoder.EmitJMP(_target); // b methodEntryPoint } else { encoder.EmitMOV(encoder.TargetRegister.InterproceduralScratch, _target); encoder.EmitJMP(encoder.TargetRegister.InterproceduralScratch); } }
protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) { // First load the generic context into the context register. EmitLoadGenericContext(factory, ref encoder, relocsOnly); Register contextRegister = GetContextRegister(ref encoder); switch (_id) { case ReadyToRunHelperId.GetNonGCStaticBase: { ARMDebug.EmitNYIAssert(factory, ref encoder, "GetNonGCStaticBase EmitCode is not implemented"); /* *** ***NOT TESTED!!! *** ***Debug.Assert(contextRegister == encoder.TargetRegister.Arg0); *** ***MetadataType target = (MetadataType)_target; *** ***if (!factory.TypeSystemContext.HasLazyStaticConstructor(target)) ***{ ***EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Result, _lookupSignature, relocsOnly); ***encoder.EmitRET(); ***} ***else ***{ ***EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg0, _lookupSignature, relocsOnly); ***encoder.EmitMOV(encoder.TargetRegister.Result, encoder.TargetRegister.Arg0); *** ***// We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. ***int cctorContextSize = NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target); ***encoder.EmitSUB(encoder.TargetRegister.Arg0, ((byte)(cctorContextSize))); ***// If we get the required state it will be necessary to restore the original value before returning ***encoder.EmitPUSH(encoder.TargetRegister.Arg0); *** ***// cmp [r0 + ptrSize], 1 ***encoder.EmitLDR(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg0, ((short)factory.Target.PointerSize)); ***encoder.EmitCMP(encoder.TargetRegister.Arg0, ((byte)1)); ***// return with restoring register ***encoder.EmitRETIfEqualPOP(encoder.TargetRegister.Arg0); *** ***// just restore after cmp ***encoder.EmitPOP(encoder.TargetRegister.Arg0); *** ***encoder.EmitLDR(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg0); ***encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); ***encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); ***}
protected override void EmitLoadGenericContext(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) { // We start with context register pointing to the MethodTable Register contextRegister = GetContextRegister(ref encoder); // Locate the VTable slot that points to the dictionary int vtableSlot = 0; if (!relocsOnly) { // The concrete slot won't be known until we're emitting data - don't ask for it in relocsOnly. vtableSlot = VirtualMethodSlotHelper.GetGenericDictionarySlot(factory, (TypeDesc)_dictionaryOwner); } int pointerSize = factory.Target.PointerSize; int slotOffset = EETypeNode.GetVTableOffset(pointerSize) + (vtableSlot * pointerSize); // Load the dictionary pointer from the VTable encoder.EmitLDR(contextRegister, contextRegister, slotOffset); }
protected virtual void EmitLoadGenericContext(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) { // Assume generic context is already loaded in the context register. }
protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) { ARMDebug.EmitNYIAssert(factory, ref encoder, "EmitCode is not implemented"); }
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(factory.MethodEntrypoint(_target)); // b methodEntryPoint }
protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) { encoder.EmitJMP(GetTarget(factory)); }
protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) { switch (Id) { case ReadyToRunHelperId.NewHelper: { TypeDesc target = (TypeDesc)Target; encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.ConstructedTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetNewObjectHelperForType(target))); } break; case ReadyToRunHelperId.VirtualCall: { MethodDesc targetMethod = (MethodDesc)Target; Debug.Assert(!targetMethod.OwningType.IsInterface); int pointerSize = factory.Target.PointerSize; int slot = 0; if (!relocsOnly) { slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod); Debug.Assert(slot != -1); } encoder.EmitLDR(encoder.TargetRegister.InterproceduralScratch, encoder.TargetRegister.Arg0, 0); encoder.EmitLDR(encoder.TargetRegister.InterproceduralScratch, encoder.TargetRegister.InterproceduralScratch, (short)(EETypeNode.GetVTableOffset(pointerSize) + (slot * pointerSize))); encoder.EmitJMP(encoder.TargetRegister.InterproceduralScratch); } break; case ReadyToRunHelperId.IsInstanceOf: { TypeDesc target = (TypeDesc)Target; encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetCastingHelperNameForType(target, false))); } break; case ReadyToRunHelperId.CastClass: { TypeDesc target = (TypeDesc)Target; encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetCastingHelperNameForType(target, true))); } break; case ReadyToRunHelperId.NewArr1: { TypeDesc target = (TypeDesc)Target; encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg0); encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.ConstructedTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetNewArrayHelperForType(target))); } break; case ReadyToRunHelperId.GetNonGCStaticBase: { MetadataType target = (MetadataType)Target; bool hasLazyStaticConstructor = factory.TypeSystemContext.HasLazyStaticConstructor(target); encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); if (!hasLazyStaticConstructor) { encoder.EmitRET(); } else { // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitSUB(encoder.TargetRegister.Arg2, ((byte)NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target))); // cmp [r2 + ptrSize], 1 encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, ((short)factory.Target.PointerSize)); encoder.EmitCMP(encoder.TargetRegister.Arg3, ((byte)1)); // return if cmp encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); encoder.EmitMOV(encoder.TargetRegister.Arg0 /*Result*/, encoder.TargetRegister.Arg2); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } } break; case ReadyToRunHelperId.GetThreadStaticBase: { MetadataType target = (MetadataType)Target; encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeThreadStaticIndex(target)); // First arg: address of the TypeManager slot that provides the helper with // information about module index and the type manager instance (which is used // for initialization on first access). encoder.EmitLDR(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg2); // Second arg: index of the type in the ThreadStatic section of the modules encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg2, ((short)factory.Target.PointerSize)); if (!factory.TypeSystemContext.HasLazyStaticConstructor(target)) { encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.GetThreadStaticBaseForType)); } else { encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitSUB(encoder.TargetRegister.Arg2, (byte)(NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target))); // TODO: performance optimization - inline the check verifying whether we need to trigger the cctor encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase)); } } break; case ReadyToRunHelperId.GetGCStaticBase: { MetadataType target = (MetadataType)Target; encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol(target)); encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Result); encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Result); if (!factory.TypeSystemContext.HasLazyStaticConstructor(target)) { encoder.EmitRET(); } else { // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); // Get cctor pointer: offset is usually equal to the double size of the pointer, therefore we can use arm sub imm encoder.EmitSUB(encoder.TargetRegister.Arg2, (byte)(NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target))); // cmp [r2 + ptrSize], 1 encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, ((short)factory.Target.PointerSize)); encoder.EmitCMP(encoder.TargetRegister.Arg3, (byte)1); // return if cmp encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); encoder.EmitMOV(encoder.TargetRegister.Arg0 /*Result*/, encoder.TargetRegister.Arg2); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase)); } } break; case ReadyToRunHelperId.DelegateCtor: { DelegateCreationInfo target = (DelegateCreationInfo)Target; if (target.TargetNeedsVTableLookup) { encoder.EmitLDR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg1); int slot = 0; if (!relocsOnly) { slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, target.TargetMethod); } Debug.Assert(slot != -1); encoder.EmitLDR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg2, ((short)(EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (slot * factory.Target.PointerSize)))); } else { ISymbolNode targetMethodNode = target.GetTargetNode(factory); encoder.EmitMOV(encoder.TargetRegister.Arg2, target.GetTargetNode(factory)); } if (target.Thunk != null) { Debug.Assert(target.Constructor.Method.Signature.Length == 3); encoder.EmitMOV(encoder.TargetRegister.Arg3, target.Thunk); } else { Debug.Assert(target.Constructor.Method.Signature.Length == 2); } encoder.EmitJMP(target.Constructor); } break; case ReadyToRunHelperId.ResolveVirtualFunction: { ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.ResolveVirtualFunction); /* *** ***NOT TESTED!!! *** ***MethodDesc targetMethod = (MethodDesc)Target; ***if (targetMethod.OwningType.IsInterface) ***{ ***encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.InterfaceDispatchCell(targetMethod)); ***encoder.EmitJMP(factory.ExternSymbol("RhpResolveInterfaceMethod")); ***} ***else ***{ ***if (relocsOnly) *** break; *** ***encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Arg0); *** ***int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod); ***Debug.Assert(slot != -1); ***encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Result, *** ((short)(EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (slot * factory.Target.PointerSize)))); ***encoder.EmitRET(); ***} */ } break; default: throw new NotImplementedException(); } }
protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) { switch (Id) { case ReadyToRunHelperId.NewHelper: { TypeDesc target = (TypeDesc)Target; encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.ConstructedTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetNewObjectHelperForType(target))); } break; case ReadyToRunHelperId.VirtualCall: { ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.VirtualCall); /* *** ***NOT TESTED!!! *** ***MethodDesc targetMethod = (MethodDesc)Target; *** ***Debug.Assert(!targetMethod.OwningType.IsInterface); *** ***int pointerSize = factory.Target.PointerSize; *** ***int slot = 0; ***if (!relocsOnly) ***{ ***slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod); ***Debug.Assert(slot != -1); ***} *** ***encoder.EmitLDR(encoder.TargetRegister.InterproceduralScratch, encoder.TargetRegister.Arg0, 0); ***encoder.EmitLDR(encoder.TargetRegister.InterproceduralScratch, encoder.TargetRegister.InterproceduralScratch, *** (short)(EETypeNode.GetVTableOffset(pointerSize) + (slot * pointerSize))); ***encoder.EmitJMP(encoder.TargetRegister.InterproceduralScratch); */ } break; case ReadyToRunHelperId.IsInstanceOf: { TypeDesc target = (TypeDesc)Target; encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetCastingHelperNameForType(target, false))); } break; case ReadyToRunHelperId.CastClass: { TypeDesc target = (TypeDesc)Target; encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetCastingHelperNameForType(target, true))); } break; case ReadyToRunHelperId.NewArr1: { TypeDesc target = (TypeDesc)Target; encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg0); encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.ConstructedTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetNewArrayHelperForType(target))); } break; case ReadyToRunHelperId.GetNonGCStaticBase: { MetadataType target = (MetadataType)Target; bool hasLazyStaticConstructor = factory.TypeSystemContext.HasLazyStaticConstructor(target); encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); if (!hasLazyStaticConstructor) { encoder.EmitRET(); } else { // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitSUB(encoder.TargetRegister.Arg2, ((byte)NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target))); // cmp [r2 + ptrSize], 1 encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, ((short)factory.Target.PointerSize)); encoder.EmitCMP(encoder.TargetRegister.Arg3, ((byte)1)); // return if cmp encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); encoder.EmitMOV(encoder.TargetRegister.Arg0 /*Result*/, encoder.TargetRegister.Arg2); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } } break; case ReadyToRunHelperId.GetThreadStaticBase: { ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.GetThreadStaticBase); /* *** ***NOT TESTED!!! *** ***MetadataType target = (MetadataType)Target; ***encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeThreadStaticIndex(target)); *** ***// First arg: address of the TypeManager slot that provides the helper with ***// information about module index and the type manager instance (which is used ***// for initialization on first access). ***encoder.EmitLDR(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg2); *** ***// Second arg: index of the type in the ThreadStatic section of the modules ***encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg2, ((short)factory.Target.PointerSize)); *** ***if (!factory.TypeSystemContext.HasLazyStaticConstructor(target)) ***{ ***encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.GetThreadStaticBaseForType)); ***} ***else ***{ ***encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); ***encoder.EmitSUB(encoder.TargetRegister.Arg2, (byte)(NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target))); ***// TODO: performance optimization - inline the check verifying whether we need to trigger the cctor ***encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase)); ***} */ }
protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) { throw new NotImplementedException(); }
protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) { switch (Id) { case ReadyToRunHelperId.NewHelper: { TypeDesc target = (TypeDesc)Target; encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.ConstructedTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetNewObjectHelperForType(target))); } break; case ReadyToRunHelperId.VirtualCall: { MethodDesc targetMethod = (MethodDesc)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.VirtualCall); } break; case ReadyToRunHelperId.IsInstanceOf: { TypeDesc target = (TypeDesc)Target; encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetCastingHelperNameForType(target, false))); } break; case ReadyToRunHelperId.CastClass: { TypeDesc target = (TypeDesc)Target; encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetCastingHelperNameForType(target, true))); } break; case ReadyToRunHelperId.NewArr1: { TypeDesc target = (TypeDesc)Target; encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg0); encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.ConstructedTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetNewArrayHelperForType(target))); } break; case ReadyToRunHelperId.GetNonGCStaticBase: { MetadataType target = (MetadataType)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.GetNonGCStaticBase); } break; case ReadyToRunHelperId.GetThreadStaticBase: { MetadataType target = (MetadataType)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.GetThreadStaticBase); } break; case ReadyToRunHelperId.GetGCStaticBase: { MetadataType target = (MetadataType)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.GetGCStaticBase); } break; case ReadyToRunHelperId.DelegateCtor: { DelegateCreationInfo target = (DelegateCreationInfo)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.DelegateCtor); } break; case ReadyToRunHelperId.ResolveVirtualFunction: { MethodDesc targetMethod = (MethodDesc)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.ResolveVirtualFunction); } break; default: throw new NotImplementedException(); } }
protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) { // First load the generic context into the context register. EmitLoadGenericContext(factory, ref encoder, relocsOnly); Register contextRegister = GetContextRegister(ref encoder); switch (_id) { case ReadyToRunHelperId.GetNonGCStaticBase: { Debug.Assert(contextRegister == encoder.TargetRegister.Arg0); EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Result, _lookupSignature, relocsOnly); MetadataType target = (MetadataType)_target; if (!factory.PreinitializationManager.HasLazyStaticConstructor(target)) { encoder.EmitRET(); } else { // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. int cctorContextSize = NonGCStaticsNode.GetClassConstructorContextSize(factory.Target); encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg0, ((short)(factory.Target.PointerSize - cctorContextSize))); encoder.EmitCMP(encoder.TargetRegister.Arg1, ((byte)1)); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); encoder.EmitSUB(encoder.TargetRegister.Arg0, ((byte)(cctorContextSize))); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } } break; case ReadyToRunHelperId.GetGCStaticBase: { Debug.Assert(contextRegister == encoder.TargetRegister.Arg0); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg0); EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Result, _lookupSignature, relocsOnly); encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Result); MetadataType target = (MetadataType)_target; if (!factory.PreinitializationManager.HasLazyStaticConstructor(target)) { encoder.EmitRET(); } else { // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. GenericLookupResult nonGcRegionLookup = factory.GenericLookup.TypeNonGCStaticBase(target); EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg2, nonGcRegionLookup, relocsOnly); int cctorContextSize = NonGCStaticsNode.GetClassConstructorContextSize(factory.Target); encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, ((short)(factory.Target.PointerSize - cctorContextSize))); encoder.EmitCMP(encoder.TargetRegister.Arg3, 1); encoder.EmitRETIfEqual(); 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)); } } break; case ReadyToRunHelperId.GetThreadStaticBase: { Debug.Assert(contextRegister == encoder.TargetRegister.Arg0); MetadataType target = (MetadataType)_target; // Look up the index cell EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg1, _lookupSignature, relocsOnly); ISymbolNode helperEntrypoint; if (factory.PreinitializationManager.HasLazyStaticConstructor(target)) { // There is a lazy class constructor. We need the non-GC static base because that's where the // class constructor context lives. GenericLookupResult nonGcRegionLookup = factory.GenericLookup.TypeNonGCStaticBase(target); EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg2, nonGcRegionLookup, relocsOnly); int cctorContextSize = NonGCStaticsNode.GetClassConstructorContextSize(factory.Target); encoder.EmitSUB(encoder.TargetRegister.Arg2, cctorContextSize); helperEntrypoint = factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase); } else { helperEntrypoint = factory.HelperEntrypoint(HelperEntrypoint.GetThreadStaticBaseForType); } // First arg: address of the TypeManager slot that provides the helper with // information about module index and the type manager instance (which is used // for initialization on first access). encoder.EmitLDR(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg1); // 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); } break; case ReadyToRunHelperId.DelegateCtor: { // This is a weird helper. Codegen populated Arg0 and Arg1 with the values that the constructor // method expects. Codegen also passed us the generic context in Arg2. // We now need to load the delegate target method into Arg2 (using a dictionary lookup) // and the optional 4th parameter, and call the ctor. Debug.Assert(contextRegister == encoder.TargetRegister.Arg2); var target = (DelegateCreationInfo)_target; EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg2, _lookupSignature, relocsOnly); if (target.Thunk != null) { Debug.Assert(target.Constructor.Method.Signature.Length == 3); encoder.EmitMOV(encoder.TargetRegister.Arg3, target.Thunk); } else { Debug.Assert(target.Constructor.Method.Signature.Length == 2); } encoder.EmitJMP(target.Constructor); } break; // These are all simple: just get the thing from the dictionary and we're done case ReadyToRunHelperId.TypeHandle: case ReadyToRunHelperId.MethodHandle: case ReadyToRunHelperId.FieldHandle: case ReadyToRunHelperId.MethodDictionary: case ReadyToRunHelperId.MethodEntry: case ReadyToRunHelperId.VirtualDispatchCell: case ReadyToRunHelperId.DefaultConstructor: case ReadyToRunHelperId.ObjectAllocator: case ReadyToRunHelperId.TypeHandleForCasting: case ReadyToRunHelperId.ConstrainedDirectCall: { EmitDictionaryLookup(factory, ref encoder, contextRegister, encoder.TargetRegister.Result, _lookupSignature, relocsOnly); encoder.EmitRET(); } break; default: throw new NotImplementedException(); } }
protected override void EmitCode(NodeFactory factory, ref ARMEmitter instructionEncoder, bool relocsOnly) { instructionEncoder.EmitPUSH(ARM.Register.R12); instructionEncoder.EmitMOV(ARM.Register.R12, factory.ExternSymbol("RhpInitialInterfaceDispatch")); instructionEncoder.EmitMOV(ARM.Register.R15, ARM.Register.R12); }
protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) { switch (Id) { case ReadyToRunHelperId.NewHelper: { TypeDesc target = (TypeDesc)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.NewHelper); } break; case ReadyToRunHelperId.VirtualCall: { MethodDesc targetMethod = (MethodDesc)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.VirtualCall); } break; case ReadyToRunHelperId.IsInstanceOf: { TypeDesc target = (TypeDesc)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.IsInstanceOf); } break; case ReadyToRunHelperId.CastClass: { TypeDesc target = (TypeDesc)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.CastClass); } break; case ReadyToRunHelperId.NewArr1: { TypeDesc target = (TypeDesc)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.NewArr1); } break; case ReadyToRunHelperId.GetNonGCStaticBase: { MetadataType target = (MetadataType)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.GetNonGCStaticBase); } break; case ReadyToRunHelperId.GetThreadStaticBase: { MetadataType target = (MetadataType)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.GetThreadStaticBase); } break; case ReadyToRunHelperId.GetGCStaticBase: { MetadataType target = (MetadataType)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.GetGCStaticBase); } break; case ReadyToRunHelperId.DelegateCtor: { DelegateCreationInfo target = (DelegateCreationInfo)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.DelegateCtor); } break; case ReadyToRunHelperId.ResolveVirtualFunction: { MethodDesc targetMethod = (MethodDesc)Target; ARMDebug.EmitHelperNYIAssert(factory, ref encoder, ReadyToRunHelperId.ResolveVirtualFunction); } break; default: throw new NotImplementedException(); } }