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); }
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); } } } } }
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)); }
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}"); }
public PropertyPlace(IPlace holder, Cci.IPropertyDefinition property, Emit.PEModuleBuilder module = null) { Contract.ThrowIfNull(property); _holder = holder; _property = (PropertySymbol)property; _module = module; }
/// <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; } } }
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); }); }
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; }
private static Cci.ITypeReference GetTypeReference( TypeSymbol type, SyntaxNode syntaxNode, Emit.PEModuleBuilder moduleBuilder, DiagnosticBag diagnostics ) { return(moduleBuilder.Translate(type, syntaxNode, diagnostics)); }
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); // } //} } } }
/// <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); } }
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); }
/// <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); }
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); }
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); } }
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); }
/// <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); } } } } }
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); } }
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); }
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); }
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); } } }
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)); }
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); } } }