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));
                 ***}
Esempio n. 2
0
        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.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.
                    int cctorContextSize = NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, 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);
                encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Result);

                MetadataType target = (MetadataType)_target;
                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.
                    GenericLookupResult nonGcRegionLookup = factory.GenericLookup.TypeNonGCStaticBase(target);
                    EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg2, nonGcRegionLookup, relocsOnly);

                    int cctorContextSize = NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, 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.TypeSystemContext.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.GetClassConstructorContextStorageSize(factory.Target, 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:
            {
                ARMDebug.EmitNYIAssert(factory, ref encoder, "DelegateCtor EmitCode is not implemented");

                /*
                 ***
                 ***NOT TESTED!!!
                 ***
                 ***// 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);
                 */
            }
 protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly)
 {
     ARMDebug.EmitNYIAssert(factory, ref encoder, "EmitCode is not implemented");
 }