File: Emitter\Model\SynthesizedPrivateImplementationDetailsStaticConstructor.cs
Web Access
Project: src\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.PooledObjects;
 
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
    internal sealed class SynthesizedPrivateImplementationDetailsStaticConstructor : SynthesizedGlobalMethodSymbol
    {
        internal SynthesizedPrivateImplementationDetailsStaticConstructor(SynthesizedPrivateImplementationDetailsType privateImplementationType, NamedTypeSymbol voidType)
            : base(privateImplementationType, voidType, WellKnownMemberNames.StaticConstructorName)
        {
            this.SetParameters(ImmutableArray<ParameterSymbol>.Empty);
        }
 
        public override MethodKind MethodKind => MethodKind.StaticConstructor;
 
        internal override bool HasSpecialName => true;
 
        internal override void GenerateMethodBody(TypeCompilationState compilationState, BindingDiagnosticBag diagnostics)
        {
            CSharpSyntaxNode syntax = this.GetNonNullSyntaxNode();
            SyntheticBoundNodeFactory factory = new SyntheticBoundNodeFactory(this, syntax, compilationState, diagnostics);
            factory.CurrentFunction = this;
            ArrayBuilder<BoundStatement> body = ArrayBuilder<BoundStatement>.GetInstance();
 
            // Initialize the payload root for each kind of dynamic analysis instrumentation.
            // A payload root is an array of arrays of per-method instrumentation payloads.
            // For each kind of instrumentation:
            //
            //     payloadRoot = new T[MaximumMethodDefIndex + 1][];
            //
            // where T is the type of the payload at each instrumentation point, and MaximumMethodDefIndex is the
            // index portion of the greatest method definition token in the compilation. This guarantees that any
            // method can use the index portion of its own method definition token as an index into the payload array.
 
            try
            {
                foreach (KeyValuePair<int, InstrumentationPayloadRootField> payloadRoot in ContainingPrivateImplementationDetailsType.GetInstrumentationPayloadRoots())
                {
                    int analysisKind = payloadRoot.Key;
                    ArrayTypeSymbol payloadArrayType = (ArrayTypeSymbol)payloadRoot.Value.Type.GetInternalSymbol();
 
                    BoundStatement payloadInitialization =
                        factory.Assignment(
                            factory.InstrumentationPayloadRoot(analysisKind, payloadArrayType),
                            factory.Array(payloadArrayType.ElementType, factory.Binary(BinaryOperatorKind.Addition, factory.SpecialType(SpecialType.System_Int32), factory.MaximumMethodDefIndex(), factory.Literal(1))));
                    body.Add(payloadInitialization);
                }
 
                // Initialize the module version ID (MVID) field. Dynamic instrumentation requires the MVID of the executing module, and this field makes that accessible.
                // MVID = new Guid(ModuleVersionIdString);
                body.Add(
                    factory.Assignment(
                       factory.ModuleVersionId(),
                       factory.New(
                           factory.WellKnownMethod(WellKnownMember.System_Guid__ctor),
                           factory.ModuleVersionIdString())));
            }
            catch (SyntheticBoundNodeFactory.MissingPredefinedMember missing)
            {
                diagnostics.Add(missing.Diagnostic);
            }
 
            BoundStatement returnStatement = factory.Return();
            body.Add(returnStatement);
 
            factory.CloseMethod(factory.Block(body.ToImmutableAndFree()));
        }
    }
}