void GenerateFieldAccessorProperty(Emit.PEModuleBuilder module, DiagnosticBag diagnostics, SourceFieldSymbol srcf, PropertySymbol paccessor)
        {
            //
            module.SynthesizedManager.AddProperty(this, paccessor);

            //
            var get_body = MethodGenerator.GenerateMethodBody(module, paccessor.GetMethod, (il) =>
            {
                // Template: return field;
                var place = new FieldPlace(new ArgPlace(this, 0), srcf.OverridenDefinition, module);
                place.EmitLoad(il);
                il.EmitRet(false);
            }, null, diagnostics, false);

            module.SetMethodBody(paccessor.GetMethod, get_body);
            module.SynthesizedManager.AddMethod(this, paccessor.GetMethod);

            //
            var set_body = MethodGenerator.GenerateMethodBody(module, paccessor.SetMethod, (il) =>
            {
                // Template: field = value;
                var place = new FieldPlace(new ArgPlace(this, 0), srcf.OverridenDefinition, module);
                place.EmitStorePrepare(il);
                new ArgPlace(this, 1).EmitLoad(il);
                place.EmitStore(il);
                il.EmitRet(true);
            }, null, diagnostics, false);

            module.SetMethodBody(paccessor.SetMethod, set_body);
            module.SynthesizedManager.AddMethod(this, paccessor.SetMethod);
        }
Esempio n. 2
0
        internal void SynthesizeInit(Emit.PEModuleBuilder module, DiagnosticBag diagnostics)
        {
            if (!IsInterface)
            {
                module.EmitBootstrap(this);
            }

            // .cctor
            EmitFieldsCctor(module);

            // __statics.Init
            ((SynthesizedStaticFieldsHolder)this.StaticsContainer)?.EmitCtors(module);

            // IPhpCallable { Invoke, ToPhpValue }
            EmitPhpCallable(module, diagnostics);

            // IDisposable { Dispose }
            EmitDisposable(module, diagnostics);

            // .ctor
            EmitPhpCtors(this.InstanceConstructors, module, diagnostics);

            // System.ToString
            EmitToString(module);

            // trait methods
            EmitTraitImplementations(module);
        }
        void EmitFieldsCctor(Emit.PEModuleBuilder module)
        {
            // list app static fields
            var sflds = GetMembers().OfType <IPhpPropertySymbol>()
                        .Where(f => f.FieldKind == PhpPropertyKind.AppStaticField)
                        .ToList();

            if (sflds.Count != 0)
            {
                // emit initialization of app static fields
                // note, their initializers do not have Context available, since they are not bound to a Context

                var cctor = module.GetStaticCtorBuilder(this);
                lock (cctor)
                {
                    using (var cg = new CodeGenerator(cctor, module, DiagnosticBag.GetInstance(), module.Compilation.Options.OptimizationLevel, false, this, null, thisPlace: null)
                    {
                        CallerType = this,
                        ContainingFile = this.ContainingFile,
                    })
                    {
                        foreach (var f in sflds)
                        {
                            Debug.Assert(f.RequiresContext == false);
                            Debug.Assert(f.ContainingStaticsHolder == null);

                            f.EmitInit(cg);
                        }
                    }
                }
            }
        }
Esempio n. 4
0
        void EmitInit(Emit.PEModuleBuilder module)
        {
            EnsureMembers();

            // void Init(Context)

            var tt         = DeclaringCompilation.CoreTypes;
            var diagnostic = DiagnosticBag.GetInstance();

            // override IStaticInit.Init(Context) { .. }

            var initMethod = new SynthesizedMethodSymbol(this, "Init", false, true, tt.Void, Accessibility.Public);

            initMethod.SetParameters(new SynthesizedParameterSymbol(initMethod, tt.Context, 0, RefKind.None, "ctx"));

            var body = MethodGenerator.GenerateMethodBody(module, initMethod, (il) =>
            {
                var cg = new CodeGenerator(il, module, diagnostic, OptimizationLevel.Release, false, this, new ArgPlace(tt.Context, 1), new ArgPlace(this, 0));

                GetMembers().OfType <SourceFieldSymbol>().Where(f => f.InitializerRequiresContext).ForEach(f => f.EmitInit(cg));

                //
                il.EmitRet(true);
            },
                                                          null, diagnostic, false);

            module.SetMethodBody(initMethod, body);

            //
            _lazyMembers = _lazyMembers.Add(initMethod);
        }
        void EmitInit(Emit.PEModuleBuilder module)
        {
            // void Init(Context)

            var tt         = DeclaringCompilation.CoreTypes;
            var diagnostic = DiagnosticBag.GetInstance();

            // override IStaticInit.Init(Context) { .. }

            var initMethod = new SynthesizedMethodSymbol(this, "Init", false, true, tt.Void, Accessibility.Public);

            initMethod.SetParameters(new SynthesizedParameterSymbol(initMethod, tt.Context, 0, RefKind.None, "ctx"));

            var body = MethodGenerator.GenerateMethodBody(module, initMethod, (il) =>
            {
                var cg = new CodeGenerator(il, module, diagnostic, module.Compilation.Options.OptimizationLevel, false, this, new ArgPlace(tt.Context, 1), new ArgPlace(this, 0));

                foreach (var fld in this.Fields)
                {
                    if (fld.RequiresContext)
                    {
                        fld.EmitInit(cg);
                    }
                }

                //
                il.EmitRet(true);
            },
                                                          null, diagnostic, false);

            module.SetMethodBody(initMethod, body);
            module.SynthesizedManager.AddMethod(this, initMethod);
        }
        void EmitPhpCallable(Emit.PEModuleBuilder module, DiagnosticBag diagnostics)
        {
            var __invoke = TryGetMagicInvoke();

            if (__invoke == null ||
                IsAlreadyImplemented(__invoke) ||
                IsAlreadyImplemented(DeclaringCompilation.CoreTypes.IPhpCallable))
            {
                // already implemented in a base class
                return;
            }

            //
            // IPhpCallable.Invoke(Context <ctx>, PhpVaue[] arguments)
            //
            var invoke = new SynthesizedMethodSymbol(this, "IPhpCallable.Invoke", false, true, DeclaringCompilation.CoreTypes.PhpValue, isfinal: false)
            {
                ExplicitOverride = (MethodSymbol)DeclaringCompilation.CoreTypes.IPhpCallable.Symbol.GetMembers("Invoke").Single(),
                ForwardedCall    = __invoke,
            };

            invoke.SetParameters(
                new SpecialParameterSymbol(invoke, DeclaringCompilation.CoreTypes.Context, SpecialParameterSymbol.ContextName, 0),
                new SynthesizedParameterSymbol(invoke, ArrayTypeSymbol.CreateSZArray(ContainingAssembly, DeclaringCompilation.CoreTypes.PhpValue.Symbol), 1, RefKind.None, name: "arguments", isParams: true));

            module.SetMethodBody(invoke, MethodGenerator.GenerateMethodBody(module, invoke, il =>
            {
                var cg = new CodeGenerator(il, module, diagnostics, module.Compilation.Options.OptimizationLevel, false, this, new ParamPlace(invoke.Parameters[0]), new ArgPlace(this, 0))
                {
                    CallerType = this,
                };

                cg.EmitRet(cg.EmitForwardCall(__invoke, invoke, callvirt: true));
            }, null, diagnostics, false));

            module.SynthesizedManager.AddMethod(this, invoke);

            //
            // IPhpCallable.ToPhpValue()
            //
            var tophpvalue = new SynthesizedMethodSymbol(this, "IPhpCallable.ToPhpValue", false, true, DeclaringCompilation.CoreTypes.PhpValue, isfinal: false)
            {
                ExplicitOverride = (MethodSymbol)DeclaringCompilation.CoreTypes.IPhpCallable.Symbol.GetMembers("ToPhpValue").Single(),
            };

            //
            module.SetMethodBody(tophpvalue, MethodGenerator.GenerateMethodBody(module, tophpvalue, il =>
            {
                var thisPlace = new ArgPlace(this, 0);
                var ctxPlace  = new FieldPlace(thisPlace, this.ContextStore, module);
                var cg        = new CodeGenerator(il, module, diagnostics, module.Compilation.Options.OptimizationLevel, false, this, ctxPlace, thisPlace);

                // return PhpValue.FromClass(this)
                cg.EmitThis();
                cg.EmitRet(cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.FromClass_Object));
            }, null, diagnostics, false));

            module.SynthesizedManager.AddMethod(this, tophpvalue);
        }
            internal sealed override void AddSynthesizedAttributes(Emit.PEModuleBuilder modulebuilder, ref ArrayBuilder <SynthesizedAttributeData> attributes)
            {
                base.AddSynthesizedAttributes(modulebuilder, ref attributes);

                var compilation = this.DeclaringCompilation;

                AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_ParamArrayAttribute__ctor));
            }
Esempio n. 8
0
        public FieldPlace(IPlace holder, IFieldSymbol field, Emit.PEModuleBuilder module = null)
            : base(field, module)
        {
            _holder = holder;

            Debug.Assert(holder != null || field.IsStatic, "receiver not set");
            Debug.Assert(holder == null || holder.Type.IsOfType(_field.ContainingType) || _field.ContainingType.IsValueType, $"receiver of type {holder?.Type} mismatches the field's containing type {_field?.ContainingType}");
        }
Esempio n. 9
0
        public PropertyPlace(IPlace holder, Cci.IPropertyDefinition property, Emit.PEModuleBuilder module = null)
        {
            Contract.ThrowIfNull(property);

            _holder   = holder;
            _property = (PropertySymbol)property;
            _module   = module;
        }
Esempio n. 10
0
        /// <summary>
        /// Collects methods that has to be overriden and matches with this declaration.
        /// Missing overrides are reported, needed ghost stubs are synthesized.
        /// </summary>
        public void FinalizeMethodTable(Emit.PEModuleBuilder module, DiagnosticBag diagnostics)
        {
            // creates ghost stubs for overrides that do not match the signature

            foreach (var info in this.ResolveOverrides(diagnostics))
            {
                // note: unresolved abstracts already reported by ResolveOverrides

                // is ghost stub needed?

                if (ReferenceEquals(info.OverrideCandidate?.ContainingType, this) ||    // candidate not matching exactly the signature in this type
                    info.ImplementsInterface)                                           // explicitly implement the interface
                {
                    if (info.HasOverride)
                    {
                        if (info.ImplementsInterface && info.Override != null)
                        {
                            // create explicit override only if the interface method is implemented with a class method that does not implement the interface

                            /*
                             * interface I { foo }  // METHOD
                             * class X { foo }      // OVERRIDE
                             * class Y : X, I { explicit I.foo override }   // GHOST
                             */
                            if (info.Override.ContainingType.ImplementsInterface(info.Method.ContainingType))
                            {
                                /* => X implements I */
                                // explicit method override is not needed
                                continue;
                            }
                        }

                        /*
                         * class A {
                         *    TReturn1 foo(A, B);
                         * }
                         * class B : A {
                         *    TReturn2 foo(A2, B2);
                         *
                         *    // SYNTHESIZED GHOST:
                         *    override TReturn foo(A, B){ return (TReturn)foo((A2)A, (B2)B);
                         * }
                         */

                        // override method with a ghost that calls the override
                        (info.Override ?? info.OverrideCandidate).CreateGhostOverload(
                            this, module, diagnostics,
                            info.Method.ReturnType, info.Method.Parameters, info.Method);
                    }
                }

                // setup synthesized methods explicit override as resolved
                if (info.Override is SynthesizedMethodSymbol sm && sm.ExplicitOverride == null && sm.ContainingType == this)
                {
                    sm.ExplicitOverride = info.Method;
                }
            }
        }
Esempio n. 11
0
        void EmitInit(Emit.PEModuleBuilder module, DiagnosticBag diagnostic, PhpCompilation compilation, SynthesizedStaticLocHolder holder, BoundExpression initializer)
        {
            var loctype = holder.ValueField.Type;

            bool requiresContext = initializer != null && initializer.RequiresContext;

            if (requiresContext)
            {
                // emit Init only if it needs Context

                holder.EmitInit(module, (il) =>
                {
                    var cg = new CodeGenerator(il, module, diagnostic, OptimizationLevel.Release, false,
                                               holder.ContainingType, new ArgPlace(compilation.CoreTypes.Context, 1), new ArgPlace(holder, 0));

                    var valuePlace = new FieldPlace(cg.ThisPlaceOpt, holder.ValueField);

                    // Template: this.value = <initilizer>;

                    valuePlace.EmitStorePrepare(il);
                    cg.EmitConvert(initializer, valuePlace.TypeOpt);
                    valuePlace.EmitStore(il);

                    //
                    il.EmitRet(true);
                });
            }

            // default .ctor
            holder.EmitCtor(module, (il) =>
            {
                if (!requiresContext)
                {
                    // emit default value only if it won't be initialized by Init above

                    var cg = new CodeGenerator(il, module, diagnostic, OptimizationLevel.Release, false,
                                               holder.ContainingType, null, new ArgPlace(holder, 0));

                    var valuePlace = new FieldPlace(cg.ThisPlaceOpt, holder.ValueField);

                    // Template: this.value = default(T);

                    valuePlace.EmitStorePrepare(il);
                    if (initializer != null)
                    {
                        cg.EmitConvert(initializer, valuePlace.TypeOpt);
                    }
                    else
                    {
                        cg.EmitLoadDefault(valuePlace.TypeOpt, 0);
                    }
                    valuePlace.EmitStore(il);
                }

                //
                il.EmitRet(true);
            });
        }
Esempio n. 12
0
        public FieldPlace_Raw(IFieldSymbol field, Emit.PEModuleBuilder module = null)
        {
            Contract.ThrowIfNull(field);

            field = GetRealDefinition(field);

            _field    = (FieldSymbol)field;
            _fieldref = (module != null) ? module.Translate((FieldSymbol)field, null, DiagnosticBag.GetInstance()) : (Cci.IFieldReference)field;
        }
Esempio n. 13
0
 private static Cci.ITypeReference GetTypeReference(
     TypeSymbol type,
     SyntaxNode syntaxNode,
     Emit.PEModuleBuilder moduleBuilder,
     DiagnosticBag diagnostics
     )
 {
     return(moduleBuilder.Translate(type, syntaxNode, diagnostics));
 }
Esempio n. 14
0
        void EmitTraitImplementations(Emit.PEModuleBuilder module)
        {
            foreach (var t in TraitUses)
            {
                foreach (var m in t.GetMembers().OfType <SynthesizedMethodSymbol>())
                {
                    Debug.Assert(m.ForwardedCall != null);

                    module.SetMethodBody(m, MethodGenerator.GenerateMethodBody(module, m, il =>
                    {
                        IPlace thisPlace          = null;
                        IPlace traitInstancePlace = null;
                        IPlace ctxPlace;

                        if (m.IsStatic)
                        {
                            // Template: return TRAIT.method(...)
                            Debug.Assert(SpecialParameterSymbol.IsContextParameter(m.Parameters[0]));
                            ctxPlace = new ParamPlace(m.Parameters[0]);
                        }
                        else
                        {
                            // Template: return this.<>trait.method(...)
                            thisPlace          = new ArgPlace(this, 0);                                   // this
                            ctxPlace           = new FieldPlace(thisPlace, this.ContextStore, module);    // this.<ctx>
                            traitInstancePlace = new FieldPlace(thisPlace, t.TraitInstanceField, module); // this.<>trait
                        }

                        using (var cg = new CodeGenerator(il, module, DiagnosticBag.GetInstance(), module.Compilation.Options.OptimizationLevel, false, this, ctxPlace, thisPlace)
                        {
                            CallerType = this,
                        })
                        {
                            var forwarded_type = cg.EmitForwardCall(m.ForwardedCall, m, thisPlaceExplicit: traitInstancePlace);
                            var target_type    = m.ReturnType;

                            cg.EmitConvert(forwarded_type, 0, target_type); // always (forwarded_type === target_type)
                            cg.EmitRet(target_type);
                        }
                    }, null, DiagnosticBag.GetInstance(), false));
                    module.SynthesizedManager.AddMethod(this, m);

                    // NOTE: following is not needed anymore:
                    //// ghost stubs: // ... resolve this already in SourceTypeSymbol.GetMembers(), now it does not get overloaded properly
                    //var ps = m.Parameters;
                    //for (int i = 0; i < ps.Length; i++)
                    //{
                    //    if (ps[i].HasUnmappedDefaultValue())  // => ConstantValue couldn't be resolved for optional parameter
                    //    {
                    //        // create ghost stub foo(p0, .. pi-1) => foo(p0, .. , pN)
                    //        GhostMethodBuilder.CreateGhostOverload(m, module, DiagnosticBag.GetInstance(), i);
                    //    }
                    //}
                }
            }
        }
Esempio n. 15
0
        /// <summary>
        /// A field representing the function info at runtime.
        /// Lazily associated with index by runtime.
        /// </summary>
        internal FieldSymbol EnsureRoutineInfoField(Emit.PEModuleBuilder module)
        {
            if (_lazyRoutineInfoField == null)
            {
                _lazyRoutineInfoField = module.SynthesizedManager
                                        .GetOrCreateSynthesizedField(_container, this.DeclaringCompilation.CoreTypes.RoutineInfo, $"[routine]{this.MetadataName}", Accessibility.Internal, true, true, true);
            }

            return(_lazyRoutineInfoField);
        }
        void EmitToString(Emit.PEModuleBuilder module)
        {
            if (this.IsInterface || this.IsTrait)
            {
                return;
            }

            var __tostring = this.GetMembersByPhpName(SpecialMethodNames.Tostring.Value).OfType <MethodSymbol>().FirstOrDefault();

            if (__tostring != null)    // implement ToString if: there is __toString() function
            {
                // lookup base string ToString()
                var overriden = this.LookupMember <MethodSymbol>(
                    WellKnownMemberNames.ObjectToString,
                    m => OverrideHelper.SignaturesMatch(m, (MethodSymbol)DeclaringCompilation.GetSpecialTypeMember(SpecialMember.System_Object__ToString)));

                Debug.Assert(overriden != null);

                if (overriden == null || overriden.IsSealed || overriden.ContainingType == this)
                {
                    // cannot be overriden
                    return;
                }

                // public sealed override string ToString()
                var tostring = new SynthesizedMethodSymbol(this, WellKnownMemberNames.ObjectToString, false, true, DeclaringCompilation.CoreTypes.String, Accessibility.Public, isfinal: false, phphidden: true)
                {
                    ExplicitOverride = overriden,
                    ForwardedCall    = __tostring,
                };

                module.SetMethodBody(tostring, MethodGenerator.GenerateMethodBody(module, tostring, il =>
                {
                    var thisPlace = new ArgPlace(this, 0);
                    var cg        = new CodeGenerator(il, module, DiagnosticBag.GetInstance(), module.Compilation.Options.OptimizationLevel, false, this, new FieldPlace(thisPlace, this.ContextStore, module), thisPlace);

                    if (__tostring != null)
                    {
                        // __tostring().ToString()
                        cg.EmitConvert(cg.EmitForwardCall(__tostring, tostring, callvirt: true), 0, tostring.ReturnType);
                    }
                    else
                    {
                        // PhpException.ObjectToStringNotSupported(this)
                        cg.EmitThis();
                        cg.EmitPop(cg.EmitCall(ILOpCode.Call, cg.CoreTypes.PhpException.Method("ObjectToStringNotSupported", cg.CoreTypes.Object)));

                        // return ""
                        cg.Builder.EmitStringConstant(string.Empty);
                    }
                    cg.EmitRet(tostring.ReturnType);
                }, null, DiagnosticBag.GetInstance(), false));
                module.SynthesizedManager.AddMethod(this, tostring);
            }
        }
Esempio n. 17
0
        void EmitPhpCtors(ImmutableArray <MethodSymbol> instancectors, Emit.PEModuleBuilder module, DiagnosticBag diagnostics)
        {
            foreach (SynthesizedPhpCtorSymbol ctor in instancectors)
            {
                module.SetMethodBody(ctor, MethodGenerator.GenerateMethodBody(module, ctor, il =>
                {
                    Debug.Assert(SpecialParameterSymbol.IsContextParameter(ctor.Parameters[0]));

                    var cg = new CodeGenerator(il, module, diagnostics, OptimizationLevel.Release, false, this, new ParamPlace(ctor.Parameters[0]), new ArgPlace(this, 0));

                    Debug.Assert(ctor.BaseCtor != null);

                    // base..ctor or this..ctor
                    cg.EmitPop(cg.EmitThisCall(ctor.BaseCtor, ctor));

                    if (ctor.PhpConstructor == null)
                    {
                        // initialize <ctx> field, if field is declared within this type
                        var ctxField = this.ContextStore;
                        if (ctxField != null && object.ReferenceEquals((object)ctxField.ContainingType, this))
                        {
                            var ctxFieldPlace = new FieldPlace(cg.ThisPlaceOpt, ctxField);

                            // Debug.Assert(<ctx> != null)
                            cg.EmitDebugAssertNotNull(cg.ContextPlaceOpt, "Context cannot be null.");

                            // <this>.<ctx> = <ctx>
                            ctxFieldPlace.EmitStorePrepare(il);
                            cg.EmitLoadContext();
                            ctxFieldPlace.EmitStore(il);
                        }

                        // initialize class fields
                        foreach (var fld in this.EnsureMembers().OfType <SourceFieldSymbol>().Where(fld => !fld.RequiresHolder && !fld.IsStatic && !fld.IsConst))
                        {
                            fld.EmitInit(cg);
                        }
                    }
                    else
                    {
                        Debug.Assert(ctor.BaseCtor.ContainingType == this);

                        // this.__construct
                        cg.EmitPop(cg.EmitThisCall(ctor.PhpConstructor, ctor));
                    }

                    // ret
                    Debug.Assert(ctor.ReturnsVoid);
                    cg.EmitRet(ctor.ReturnType);
                }, null, diagnostics, false));
            }
        }
        public void EmitCtor(Emit.PEModuleBuilder module, Action <Microsoft.CodeAnalysis.CodeGen.ILBuilder> builder)
        {
            Debug.Assert(_ctor == null);

            // emit default .ctor

            _ctor = new SynthesizedCtorSymbol(this);
            _ctor.SetParameters();// empty params (default ctor)

            var body = CodeGen.MethodGenerator.GenerateMethodBody(module, _ctor, builder, null, DiagnosticBag.GetInstance(), false);

            module.SetMethodBody(_ctor, body);
        }
Esempio n. 19
0
        /// <summary>
        /// A field representing the function info at runtime of type <c>RoutineInfo</c>.
        /// Lazily associated with index by runtime.
        /// </summary>
        internal FieldSymbol EnsureRoutineInfoField(Emit.PEModuleBuilder module)
        {
            if (_lazyRoutineInfoField == null)
            {
                _lazyRoutineInfoField = module.SynthesizedManager
                                        .GetOrCreateSynthesizedField(_file, this.DeclaringCompilation.CoreTypes.RoutineInfo, "<>" + this.MetadataName,
                                                                     accessibility: Accessibility.Internal,
                                                                     isstatic: true,
                                                                     @readonly: true);
            }

            return(_lazyRoutineInfoField);
        }
Esempio n. 20
0
        internal void EmitInit(Emit.PEModuleBuilder module)
        {
            var cctor = module.GetStaticCtorBuilder(_file);
            var field = new FieldPlace(null, this.EnsureRoutineInfoField(module));

            // {RoutineInfoField} = RoutineInfo.CreateUserRoutine(name, handle)
            field.EmitStorePrepare(cctor);

            cctor.EmitStringConstant(this.QualifiedName.ToString());
            cctor.EmitLoadToken(module, DiagnosticBag.GetInstance(), this, null);
            cctor.EmitCall(module, DiagnosticBag.GetInstance(), System.Reflection.Metadata.ILOpCode.Call, module.Compilation.CoreMethods.Reflection.CreateUserRoutine_string_RuntimeMethodHandle);

            field.EmitStore(cctor);
        }
Esempio n. 21
0
        internal void EmitCtors(Emit.PEModuleBuilder module)
        {
            bool requiresInit = false;

            // .ctor()

            var tt         = DeclaringCompilation.CoreTypes;
            var diagnostic = DiagnosticBag.GetInstance();

            var ctor = new SynthesizedCtorSymbol(this);

            var body = MethodGenerator.GenerateMethodBody(module, ctor, (il) =>
            {
                var cg = new CodeGenerator(il, module, diagnostic, module.Compilation.Options.OptimizationLevel, false, this, null, new ArgPlace(this, 0))
                {
                    CallerType     = this.ContainingType,
                    ContainingFile = _class.ContainingFile,
                };

                // base..ctor()
                cg.EmitThis();                                                                               // this
                il.EmitCall(module, diagnostic, ILOpCode.Call, this.BaseType.InstanceConstructors.Single()); // .ctor()

                //
                foreach (var p in this.Fields.Cast <IPhpPropertySymbol>())
                {
                    if (p.RequiresContext)
                    {
                        requiresInit = true;
                    }
                    else
                    {
                        p.EmitInit(cg);
                    }
                }

                //
                il.EmitRet(true);
            },
                                                          null, diagnostic, false);

            module.SetMethodBody(ctor, body);
            module.SynthesizedManager.AddMethod(this, ctor);

            //
            if (requiresInit)
            {
                EmitInit(module);
            }
        }
Esempio n. 22
0
        public Cci.IImportScope Translate(Emit.PEModuleBuilder moduleBuilder, DiagnosticBag diagnostics)
        {
            for (var scope = this; scope != null; scope = scope.ParentOpt)
            {
                if (!scope._lazyTranslatedImports.IsDefault)
                {
                    break;
                }

                ImmutableInterlocked.InterlockedInitialize(ref scope._lazyTranslatedImports, scope.TranslateImports(moduleBuilder, diagnostics));
            }

            return(this);
        }
        public void EmitInit(Emit.PEModuleBuilder module, Action <Microsoft.CodeAnalysis.CodeGen.ILBuilder> builder)
        {
            Debug.Assert(_initMethod == null);

            var tt = DeclaringCompilation.CoreTypes;

            // override IStaticInit.Init(Context)

            _initMethod = new SynthesizedMethodSymbol(this, "Init", false, true, tt.Void, Accessibility.Public);
            _initMethod.SetParameters(new SynthesizedParameterSymbol(_initMethod, tt.Context, 0, RefKind.None, "ctx"));

            var body = CodeGen.MethodGenerator.GenerateMethodBody(module, _initMethod, builder, null, DiagnosticBag.GetInstance(), false);

            module.SetMethodBody(_initMethod, body);
        }
Esempio n. 24
0
        /// <summary>
        /// Collects methods that has to be overriden and matches with this declaration.
        /// Missing overrides are reported, needed ghost stubs are synthesized.
        /// </summary>
        public void FinalizeMethodTable(Emit.PEModuleBuilder module, DiagnosticBag diagnostics)
        {
            // creates ghost stubs for overrides that do not match the signature

            foreach (var info in this.ResolveOverrides(diagnostics))
            {
                // note: unresolved abstracts already reported by ResolveOverrides

                // is a ghost stub needed?

                if (ReferenceEquals(info.OverrideCandidate?.ContainingType, this) || // candidate not matching exactly the signature in this type -> create ghost stub
                    info.ImplementsInterface)                                        // explicitly implement the interface -> ghost stub
                {
                    if (info.HasOverride)
                    {
                        /*
                         * class A {
                         *    TReturn1 foo(A, B);
                         * }
                         * class B : A {
                         *    TReturn2 foo(A2, B2);
                         *
                         *    // SYNTHESIZED GHOST:
                         *    override TReturn foo(A, B){ return (TReturn)foo((A2)A, (B2)B);
                         * }
                         */

                        // override method with a ghost that calls the override
                        try
                        {
                            (info.Override ?? info.OverrideCandidate).CreateGhostOverload(
                                this, module, diagnostics,
                                info.Method.ReturnType, info.Method.Parameters, info.Method);
                        }
                        catch (NotImplementedException na)
                        {
                            if (string.IsNullOrEmpty(na.Message))
                            {
                                throw;
                            }

                            var o = info.Override ?? info.OverrideCandidate;
                            throw new NotImplementedException($"{na.Message} when emitting ghost stub of {o.ContainingType.Name}::{o.RoutineName}() overriding {info.Method.ContainingType.Name}::{info.Method.RoutineName} within type {this.Name}.", na);
                        }
                    }
                }
            }
        }
Esempio n. 25
0
        internal void EmitCtors(Emit.PEModuleBuilder module)
        {
            EnsureMembers();

            bool requiresInit = false;

            // .ctor()

            var tt         = DeclaringCompilation.CoreTypes;
            var diagnostic = DiagnosticBag.GetInstance();

            var ctor = new SynthesizedCtorSymbol(this);

            ctor.SetParameters();// empty params (default ctor)

            var body = MethodGenerator.GenerateMethodBody(module, ctor, (il) =>
            {
                var cg = new CodeGenerator(il, module, diagnostic, OptimizationLevel.Release, false, this, null, new ArgPlace(this, 0));

                foreach (var fld in GetMembers().OfType <SourceFieldSymbol>())
                {
                    if (fld.InitializerRequiresContext)
                    {
                        requiresInit = true;
                    }
                    else
                    {
                        fld.EmitInit(cg);
                    }
                }

                //
                il.EmitRet(true);
            },
                                                          null, diagnostic, false);

            module.SetMethodBody(ctor, body);

            //
            _lazyMembers = _lazyMembers.Add(ctor);

            //
            if (requiresInit)
            {
                EmitInit(module);
            }
        }
Esempio n. 26
0
        internal void EmitInit(Emit.PEModuleBuilder module, DiagnosticBag diagnostics)
        {
            // .cctor
            EmitFieldsCctor(module);

            // __statics.Init
            ((SynthesizedStaticFieldsHolder)this.StaticsContainer)?.EmitCtors(module);

            // IPhpCallable { Invoke, ToPhpValue }
            EmitPhpCallable(module, diagnostics);

            // .ctor
            EmitPhpCtors(this.InstanceConstructors, module, diagnostics);

            // System.ToString
            EmitToString(module);
        }
Esempio n. 27
0
        internal void EmitInit(Emit.PEModuleBuilder module)
        {
            // .cctor
            EmitFieldsCctor(module);

            // __statics.Init
            ((SynthesizedStaticFieldsHolder)this.StaticsContainer)?.EmitCtors(module);

            // IPhpCallable.Invoke
            EmitInvoke(EnsureInvokeMethod(module), module);

            // .phpnew
            EmitPhpNew((SynthesizedPhpNewMethodSymbol)InitializeInstanceMethod, module);

            // .ctor
            EmitPhpCtor(PhpCtorMethodSymbol, module);
        }
Esempio n. 28
0
        void EmitFieldsCctor(Emit.PEModuleBuilder module)
        {
            var sflds = GetMembers().OfType <SourceFieldSymbol>().Where(f => !f.IsConst && f.IsStatic && !f.RequiresHolder).ToList();

            if (sflds.Count != 0)
            {
                // emit initialization of app static fields
                // note, their initializers do not have Context available, since they are not bound to a Context

                var cctor = module.GetStaticCtorBuilder(this);
                var cg    = new CodeGenerator(cctor, module, DiagnosticBag.GetInstance(), OptimizationLevel.Release, false, this, null, null);

                foreach (var f in sflds)
                {
                    f.EmitInit(cg);
                }
            }
        }
Esempio n. 29
0
        void EmitPhpNew(SynthesizedPhpNewMethodSymbol phpnew, Emit.PEModuleBuilder module)
        {
            if (phpnew == null)
            {
                return;                 // static class
            }
            module.SetMethodBody(phpnew, MethodGenerator.GenerateMethodBody(module, phpnew, il =>
            {
                Debug.Assert(SpecialParameterSymbol.IsContextParameter(phpnew.Parameters[0]));

                var cg = new CodeGenerator(il, module, DiagnosticBag.GetInstance(), OptimizationLevel.Release, false, this, new ParamPlace(phpnew.Parameters[0]), new ArgPlace(this, 0));

                // initialize <ctx> field,
                // if field is declared within this type
                var ctxField = this.ContextField;
                if (ctxField != null && object.ReferenceEquals(ctxField.ContainingType, this))
                {
                    var ctxFieldPlace = new FieldPlace(cg.ThisPlaceOpt, ctxField);

                    // Debug.Assert(<ctx> != null)
                    cg.EmitDebugAssertNotNull(cg.ContextPlaceOpt, "Context cannot be null.");

                    // <this>.<ctx> = <ctx>
                    ctxFieldPlace.EmitStorePrepare(il);
                    cg.EmitLoadContext();
                    ctxFieldPlace.EmitStore(il);
                }

                // initialize class fields,
                // default(PhpValue) is not a valid value, its TypeTable must not be null
                foreach (var fld in this.GetFieldsToEmit().OfType <SourceFieldSymbol>().Where(fld => !fld.IsStatic && !fld.IsConst))
                {
                    fld.EmitInit(cg);
                }

                // base..phpnew ?? base..ctor
                var basenew = phpnew.BasePhpNew;
                Debug.Assert(basenew != null);
                cg.EmitPop(cg.EmitThisCall(basenew, phpnew));

                Debug.Assert(phpnew.ReturnsVoid);
                cg.EmitRet(true);
            }, null, DiagnosticBag.GetInstance(), false));
        }
Esempio n. 30
0
        void EmitTraitImplementations(Emit.PEModuleBuilder module)
        {
            foreach (var t in TraitUses)
            {
                foreach (var m in t.GetMembers().OfType <SynthesizedMethodSymbol>())
                {
                    Debug.Assert(m.ForwardedCall != null);

                    module.SetMethodBody(m, MethodGenerator.GenerateMethodBody(module, m, il =>
                    {
                        IPlace thisPlace          = null;
                        IPlace traitInstancePlace = null;
                        IPlace ctxPlace;

                        if (m.IsStatic)
                        {
                            // Template: return TRAIT.method(...)
                            Debug.Assert(SpecialParameterSymbol.IsContextParameter(m.Parameters[0]));
                            ctxPlace = new ParamPlace(m.Parameters[0]);
                        }
                        else
                        {
                            // Template: return this.<>trait.method(...)
                            thisPlace          = new ArgPlace(this, 0);                                   // this
                            ctxPlace           = new FieldPlace(thisPlace, this.ContextStore, module);    // this.<ctx>
                            traitInstancePlace = new FieldPlace(thisPlace, t.TraitInstanceField, module); // this.<>trait
                        }

                        using (var cg = new CodeGenerator(il, module, DiagnosticBag.GetInstance(), module.Compilation.Options.OptimizationLevel, false, this, ctxPlace, thisPlace)
                        {
                            CallerType = this,
                        })
                        {
                            var forwarded_type = cg.EmitForwardCall(m.ForwardedCall, m, thisPlaceExplicit: traitInstancePlace);
                            var target_type    = m.ReturnType;

                            cg.EmitConvert(forwarded_type, 0, target_type); // always (forwarded_type === target_type)
                            cg.EmitRet(target_type);
                        }
                    }, null, DiagnosticBag.GetInstance(), false));
                    module.SynthesizedManager.AddMethod(this, m);
                }
            }
        }