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;
            }
        }
예제 #2
0
 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);
     }
 }
예제 #4
0
        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");
 }
예제 #10
0
 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
 }
예제 #11
0
 protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly)
 {
     encoder.EmitJMP(GetTarget(factory));
 }
예제 #12
0
        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();
            }
        }
예제 #13
0
        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();
 }
예제 #15
0
        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);
 }
예제 #18
0
        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();
            }
        }