/// <summary> /// Generates ghost method body that calls <c>this</c> method. /// </summary> static void GenerateGhostBody(PEModuleBuilder module, DiagnosticBag diagnostic, MethodSymbol method, SynthesizedMethodSymbol ghost) { var containingtype = ghost.ContainingType; var body = MethodGenerator.GenerateMethodBody(module, ghost, (il) => { // $this var thisPlace = ghost.HasThis ? new ArgPlace(containingtype, 0) : null; // Context var ctxPlace = thisPlace != null && ghost.ContainingType is SourceTypeSymbol sourcetype ? new FieldPlace(thisPlace, sourcetype.ContextStore) : (IPlace) new ArgPlace(module.Compilation.CoreTypes.Context, 0); var cg = new CodeGenerator(il, module, diagnostic, module.Compilation.Options.OptimizationLevel, false, containingtype, ctxPlace, thisPlace); // return (T){routine}(p0, ..., pN); cg.EmitConvert(cg.EmitForwardCall(method, ghost), 0, ghost.ReturnType); cg.EmitRet(ghost.ReturnType); }, null, diagnostic, false); module.SetMethodBody(ghost, body); }
/// <summary> /// Generates ghost method body that calls <c>this</c> method. /// </summary> static void GenerateGhostBody(PEModuleBuilder module, DiagnosticBag diagnostic, MethodSymbol method, SynthesizedMethodSymbol ghost) { var containingtype = ghost.ContainingType; var body = MethodGenerator.GenerateMethodBody(module, ghost, (il) => { // $this var thisPlace = ghost.HasThis ? new ArgPlace(containingtype, 0) : null; // Context var ctxPlace = thisPlace != null && ghost.ContainingType is SourceTypeSymbol sourcetype ? (sourcetype.ContextStore != null ? new FieldPlace(thisPlace, sourcetype.ContextStore, module) : null) : (IPlace) new ArgPlace(module.Compilation.CoreTypes.Context, 0); // .callvirt bool callvirt = ghost.ExplicitOverride != null && ghost.ExplicitOverride.ContainingType.IsInterface; // implementing interface, otherwise we should be able to call specific method impl. non-virtually via ghost var cg = new CodeGenerator(il, module, diagnostic, module.Compilation.Options.OptimizationLevel, false, containingtype, ctxPlace, thisPlace) { DebugRoutine = ghost, }; // return (T){routine}(p0, ..., pN); cg.EmitConvert(cg.EmitForwardCall(method, ghost, callvirt: callvirt), 0, ghost.ReturnType); cg.EmitRet(ghost.ReturnType); }, null, diagnostic, false); module.SetMethodBody(ghost, body); }