diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 73669cf03a73b..c7eee212e5687 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6070,4 +6070,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Generator failed to initialize. + + module initializers + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs index 997bb6b31a945..a4af9691431ff 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs @@ -16,6 +16,7 @@ using System.Reflection.Metadata; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Symbols; @@ -2015,6 +2016,14 @@ private protected override bool IsSymbolAccessibleWithinCore( throw new NotImplementedException(); } + private ConcurrentSet? _moduleInitializerMethods; + + internal void AddModuleInitializerMethod(MethodSymbol method) + { + Debug.Assert(!_declarationDiagnosticsFrozen); + LazyInitializer.EnsureInitialized(ref _moduleInitializerMethods).Add(method); + } + #endregion #region Binding @@ -2802,6 +2811,8 @@ internal override bool CompileMethods( filterOpt: filterOpt, cancellationToken: cancellationToken); + GenerateModuleInitializer(moduleBeingBuilt, methodBodyDiagnosticBag); + bool hasMethodBodyError = !FilterAndAppendAndFreeDiagnostics(diagnostics, ref methodBodyDiagnosticBag); if (hasDeclarationErrors || hasMethodBodyError) @@ -2813,6 +2824,31 @@ internal override bool CompileMethods( return true; } + private void GenerateModuleInitializer(PEModuleBuilder moduleBeingBuilt, DiagnosticBag methodBodyDiagnosticBag) + { + Debug.Assert(_declarationDiagnosticsFrozen); + + if (_moduleInitializerMethods is object) + { + var ilBuilder = new ILBuilder(moduleBeingBuilt, new LocalSlotManager(slotAllocator: null), OptimizationLevel.Release, areLocalsZeroed: false); + + // PROTOTYPE(module-initializers): require deterministic order + foreach (var method in _moduleInitializerMethods) + { + ilBuilder.EmitOpCode(ILOpCode.Call, stackAdjustment: 0); + + ilBuilder.EmitToken( + moduleBeingBuilt.Translate(method, methodBodyDiagnosticBag, needDeclaration: true), + CSharpSyntaxTree.Dummy.GetRoot(), + methodBodyDiagnosticBag); + } + + ilBuilder.EmitRet(isVoid: true); + ilBuilder.Realize(); + moduleBeingBuilt.RootModuleType.SetStaticConstructorBody(ilBuilder.RealizedIL); + } + } + internal override bool GenerateResourcesAndDocumentationComments( CommonPEModuleBuilder moduleBuilder, Stream? xmlDocStream, diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index ee1d0255674a3..825184ddf6673 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -192,6 +192,7 @@ internal enum MessageID IDS_FeatureMemberNotNull = MessageBase + 12768, IDS_FeatureNativeInt = MessageBase + 12769, IDS_FeatureTargetTypedObjectCreation = MessageBase + 12770, + IDS_FeatureModuleInitializers = MessageBase + 12771, } // Message IDs may refer to strings that need to be localized. @@ -305,6 +306,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) case MessageID.IDS_FeatureTargetTypedObjectCreation: // syntax check case MessageID.IDS_FeatureMemberNotNull: case MessageID.IDS_FeatureNativeInt: + case MessageID.IDS_FeatureModuleInitializers: // semantic check on method attribute return LanguageVersion.Preview; // C# 8.0 features. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs index c697063b029ec..f0f9672e4feb3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs @@ -482,6 +482,12 @@ private void DecodeWellKnownAttributeAppliedToMethod(ref DecodeWellKnownAttribut MessageID.IDS_FeatureMemberNotNull.CheckFeatureAvailability(arguments.Diagnostics, arguments.AttributeSyntaxOpt); CSharpAttributeData.DecodeMemberNotNullWhenAttribute(ContainingType, ref arguments); } + else if (attribute.IsTargetAttribute(this, AttributeDescription.ModuleInitializerAttribute)) + { + MessageID.IDS_FeatureModuleInitializers.CheckFeatureAvailability(arguments.Diagnostics, arguments.AttributeSyntaxOpt); + // PROTOTYPE(module-initializers): diagnostics + DeclaringCompilation.AddModuleInitializerMethod(this); + } else { var compilation = this.DeclaringCompilation; diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 3652cf943e922..d99d9f87d50bc 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -944,6 +944,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions skrývání názvů ve vnořených funkcích diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 89f99f58ae35c..fbf7625e8ad87 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -944,6 +944,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions Namensshadowing in geschachtelten Funktionen diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 4cd1fafa42e47..c71d7b59e9882 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -944,6 +944,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions sombreado de nombres en funciones anidadas diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 62e8a589e10f8..c381951541e58 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -944,6 +944,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions ombrage des noms dans les fonctions imbriquées diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 3658daa426382..3c74d409c59e5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -944,6 +944,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions shadowing dei nomi nelle funzioni annidate diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 209c8a0cfc10d..1c448e377867c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -944,6 +944,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions 入れ子になった関数での名前シャドウイング diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 3f40cdc84e2b8..2a55ffc77840f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -944,6 +944,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions 중첩된 함수의 이름 섀도잉 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 9646a0784ee7c..d64fcc15e22a7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -944,6 +944,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions zasłanianie nazw w funkcjach zagnieżdżonych diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index bc6654efe8ed8..e4944db4ed774 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -942,6 +942,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions sombreamento de nome em funções aninhadas diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index bef3946e7ecba..a58a44f35c529 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -944,6 +944,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions скрытие имен во вложенных функциях diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 3fbf2a504f69d..61ffc836a9555 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -944,6 +944,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions iç içe işlevlerde ad gölgeleme diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 0a9d95c7c3bd3..1311c9a8a9891 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -944,6 +944,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions 在嵌套函数中的名称映射 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index d9b702bbc5e6a..743ae017dc580 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -944,6 +944,11 @@ MemberNotNull attribute + + module initializers + module initializers + + name shadowing in nested functions 巢狀函式中的名稱鏡像處理 diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/ModuleInitializersTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/ModuleInitializersTests.cs new file mode 100644 index 0000000000000..558aab4d66028 --- /dev/null +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/ModuleInitializersTests.cs @@ -0,0 +1,141 @@ +// 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. + +using System.Reflection; +using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols +{ + [CompilerTrait(CompilerFeature.ModuleInitializers)] + public sealed class ModuleInitializersTests : CSharpTestBase + { + private static readonly CSharpParseOptions s_parseOptions = TestOptions.RegularPreview; + + [Fact] + public static void LastLanguageVersionNotSupportingModuleInitializersIs8() + { + var source = +@"using System.Runtime.CompilerServices; + +class C +{ + [ModuleInitializer] + internal static void M() { } +} + +namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } +"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.Regular8); + + compilation.VerifyDiagnostics( + // (5,6): error CS8652: The feature 'module initializers' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // [ModuleInitializer] + Diagnostic(ErrorCode.ERR_FeatureInPreview, "ModuleInitializer").WithArguments("module initializers").WithLocation(5, 6) + ); + } + + [Fact] + public static void FirstLanguageVersionSupportingModuleInitializersIs9() + { + var source = +@"using System.Runtime.CompilerServices; + +class C +{ + [ModuleInitializer] + internal static void M() { } +} + +namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } +"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + } + + [Fact] + public void ModuleTypeStaticConstructorIsNotEmittedWhenNoMethodIsMarkedWithModuleInitializerAttribute() + { + string source = @" +using System; +using System.Runtime.CompilerServices; + +class C +{ + internal static void M() => Console.WriteLine(""C.M""); +} + +class Program +{ + static void Main() => Console.WriteLine(""Program.Main""); +} + +namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } +"; + + CompileAndVerify( + source, + parseOptions: s_parseOptions, + options: new CSharpCompilationOptions(OutputKind.ConsoleApplication, metadataImportOptions: MetadataImportOptions.All), + symbolValidator: module => + { + var rootModuleType = (TypeSymbol)module.GlobalNamespace.GetMember(""); + Assert.Null(rootModuleType.GetMember(".cctor")); + }, + expectedOutput: @" +Program.Main"); + } + + [Fact] + public void ModuleTypeStaticConstructorCallsMethodMarkedWithModuleInitializerAttribute() + { + string source = @" +using System; +using System.Runtime.CompilerServices; + +class C +{ + [ModuleInitializer] + internal static void M() => Console.WriteLine(""C.M""); +} + +class Program +{ + static void Main() => Console.WriteLine(""Program.Main""); +} + +namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } +"; + + CompileAndVerify( + source, + parseOptions: s_parseOptions, + options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + symbolValidator: module => + { + var rootModuleType = (TypeSymbol)module.GlobalNamespace.GetMember(""); + var staticConstructor = (PEMethodSymbol)rootModuleType.GetMember(".cctor"); + + Assert.NotNull(staticConstructor); + Assert.Equal(MethodKind.StaticConstructor, staticConstructor.MethodKind); + + var expectedFlags = + MethodAttributes.Private + | MethodAttributes.Static + | MethodAttributes.SpecialName + | MethodAttributes.RTSpecialName + | MethodAttributes.HideBySig; + + Assert.Equal(expectedFlags, staticConstructor.Flags); + }, + expectedOutput: @" +C.M +Program.Main"); + } + } +} diff --git a/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs b/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs index b21826e1bb012..e845b4632380d 100644 --- a/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs +++ b/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs @@ -459,8 +459,6 @@ internal abstract class PEModuleBuilder { - private readonly Cci.RootModuleType _rootModuleType = new Cci.RootModuleType(); - internal readonly TSourceModuleSymbol SourceModule; internal readonly TCompilation Compilation; @@ -469,6 +467,7 @@ internal abstract class PEModuleBuilder _namesOfTopLevelTypes; internal readonly TModuleCompilationState CompilationState; + public Cci.RootModuleType RootModuleType { get; } = new Cci.RootModuleType(); public abstract TEmbeddedTypesManager EmbeddedTypesManagerOpt { get; } @@ -552,9 +551,9 @@ protected bool ContainsTopLevelType(string fullEmittedName) Dispatch(typeReferenceIndexer); } - AddTopLevelType(names, _rootModuleType); - VisitTopLevelType(typeReferenceIndexer, _rootModuleType); - yield return _rootModuleType; + AddTopLevelType(names, RootModuleType); + VisitTopLevelType(typeReferenceIndexer, RootModuleType); + yield return RootModuleType; foreach (var typeDef in GetAnonymousTypeDefinitions(context)) { diff --git a/src/Compilers/Core/Portable/PEWriter/RootModuleStaticConstructor.cs b/src/Compilers/Core/Portable/PEWriter/RootModuleStaticConstructor.cs new file mode 100644 index 0000000000000..2c20dc559a616 --- /dev/null +++ b/src/Compilers/Core/Portable/PEWriter/RootModuleStaticConstructor.cs @@ -0,0 +1,162 @@ +// 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. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Reflection; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeGen; +using Microsoft.CodeAnalysis.Debugging; +using Microsoft.CodeAnalysis.Emit; +using Roslyn.Utilities; + +namespace Microsoft.Cci +{ + internal sealed partial class RootModuleStaticConstructor : IMethodDefinition, IMethodBody + { + public RootModuleStaticConstructor(ITypeDefinition containingTypeDefinition, ImmutableArray il) + { + ContainingTypeDefinition = containingTypeDefinition; + IL = il; + } + + // IMethodDefinition implementation + + public ITypeDefinition ContainingTypeDefinition { get; } + + public string Name => WellKnownMemberNames.StaticConstructorName; + + public IMethodBody GetBody(EmitContext context) => this; + + public IEnumerable GenericParameters => SpecializedCollections.EmptyEnumerable(); + + public bool IsImplicitlyDeclared => true; + + public bool HasDeclarativeSecurity => false; + + public bool IsAbstract => false; + + public bool IsAccessCheckedOnOverride => false; + + public bool IsConstructor => false; + + public bool IsExternal => false; + + public bool IsHiddenBySignature => true; + + public bool IsNewSlot => false; + + public bool IsPlatformInvoke => false; + + public bool IsRuntimeSpecial => true; + + public bool IsSealed => false; + + public bool IsSpecialName => true; + + public bool IsStatic => true; + + public bool IsVirtual => false; + + public ImmutableArray Parameters => ImmutableArray.Empty; + + public IPlatformInvokeInformation PlatformInvokeData => null; + + public bool RequiresSecurityObject => false; + + public bool ReturnValueIsMarshalledExplicitly => false; + + public IMarshallingInformation ReturnValueMarshallingInformation => null; + + public ImmutableArray ReturnValueMarshallingDescriptor => default; + + public IEnumerable SecurityAttributes => null; + + public INamespace ContainingNamespace => null; + + public TypeMemberVisibility Visibility => TypeMemberVisibility.Private; + + public bool AcceptsExtraArguments => false; + + public ushort GenericParameterCount => 0; + + public bool IsGeneric => false; + + public ImmutableArray ExtraParameters => ImmutableArray.Empty; + + public IGenericMethodInstanceReference AsGenericMethodInstanceReference => null; + + public ISpecializedMethodReference AsSpecializedMethodReference => null; + + public CallingConvention CallingConvention => CallingConvention.Default; + + public ushort ParameterCount => 0; + + public ImmutableArray ReturnValueCustomModifiers => ImmutableArray.Empty; + + public ImmutableArray RefCustomModifiers => ImmutableArray.Empty; + + public bool ReturnValueIsByRef => false; + + public IDefinition AsDefinition(EmitContext context) => this; + + public void Dispatch(MetadataVisitor visitor) => visitor.Visit((IMethodDefinition)this); + + public IEnumerable GetAttributes(EmitContext context) => SpecializedCollections.EmptyEnumerable(); + + public ITypeReference GetContainingType(EmitContext context) => ContainingTypeDefinition; + + public MethodImplAttributes GetImplementationAttributes(EmitContext context) => default; + + public ImmutableArray GetParameters(EmitContext context) => ImmutableArray.Empty; + + public IMethodDefinition GetResolvedMethod(EmitContext context) => this; + + public IEnumerable GetReturnValueAttributes(EmitContext context) => SpecializedCollections.EmptyEnumerable(); + + public ITypeReference GetType(EmitContext context) => context.Module.GetPlatformType(PlatformType.SystemVoid, context); + + // IMethodBody implementation + + public ushort MaxStack => 0; + + public ImmutableArray IL { get; } + + public IMethodDefinition MethodDefinition => this; + + public ImmutableArray ExceptionRegions => ImmutableArray.Empty; + + public bool AreLocalsZeroed => false; + + public bool HasStackalloc => false; + + public ImmutableArray LocalVariables => ImmutableArray.Empty; + + public StateMachineMoveNextBodyDebugInfo MoveNextBodyInfo => null; + + public ImmutableArray SequencePoints => ImmutableArray.Empty; + + public bool HasDynamicLocalVariables => false; + + public ImmutableArray LocalScopes => ImmutableArray.Empty; + + public IImportScope ImportScope => null; + + public DebugId MethodId => default; + + public ImmutableArray StateMachineHoistedLocalScopes => ImmutableArray.Empty; + + public string StateMachineTypeName => null; + + public ImmutableArray StateMachineHoistedLocalSlots => ImmutableArray.Empty; + + public ImmutableArray StateMachineAwaiterSlots => ImmutableArray.Empty; + + public ImmutableArray ClosureDebugInfo => ImmutableArray.Empty; + + public ImmutableArray LambdaDebugInfo => ImmutableArray.Empty; + + public DynamicAnalysisMethodBodyData DynamicAnalysisData => null; + } +} diff --git a/src/Compilers/Core/Portable/PEWriter/RootModuleType.cs b/src/Compilers/Core/Portable/PEWriter/RootModuleType.cs index 64ce7bc27441f..220de7aa6f0d5 100644 --- a/src/Compilers/Core/Portable/PEWriter/RootModuleType.cs +++ b/src/Compilers/Core/Portable/PEWriter/RootModuleType.cs @@ -4,10 +4,11 @@ #nullable enable -using System; using System.Collections.Generic; -using System.Runtime.InteropServices; +using System.Collections.Immutable; +using System.Diagnostics; using System.Reflection.Metadata; +using System.Runtime.InteropServices; using Roslyn.Utilities; using EmitContext = Microsoft.CodeAnalysis.Emit.EmitContext; @@ -18,6 +19,21 @@ namespace Microsoft.Cci /// internal class RootModuleType : INamespaceTypeDefinition { + private IReadOnlyList? _methods; + + public void SetStaticConstructorBody(ImmutableArray il) + { + Debug.Assert(_methods is null); + + _methods = SpecializedCollections.SingletonReadOnlyList( + new RootModuleStaticConstructor(containingTypeDefinition: this, il)); + } + + public IEnumerable GetMethods(EmitContext context) + { + return _methods ??= SpecializedCollections.EmptyReadOnlyList(); + } + public TypeDefinitionHandle TypeDef { get { return default(TypeDefinitionHandle); } @@ -138,11 +154,6 @@ public LayoutKind Layout get { return LayoutKind.Auto; } } - public IEnumerable GetMethods(EmitContext context) - { - return SpecializedCollections.EmptyEnumerable(); - } - public IEnumerable GetNestedTypes(EmitContext context) { return SpecializedCollections.EmptyEnumerable(); diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs index 7ac415b963564..f9cbe8c2d133f 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs @@ -428,6 +428,8 @@ static AttributeDescription() private static readonly byte[][] s_signaturesOfEnumeratorCancellationAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfNativeIntegerAttribute = { s_signature_HasThis_Void, s_signature_HasThis_Void_SzArray_Boolean }; + private static readonly byte[][] s_signaturesOfModuleInitializerAttribute = { s_signature_HasThis_Void }; + // early decoded attributes: internal static readonly AttributeDescription OptionalAttribute = new AttributeDescription("System.Runtime.InteropServices", "OptionalAttribute", s_signaturesOfOptionalAttribute); internal static readonly AttributeDescription ComImportAttribute = new AttributeDescription("System.Runtime.InteropServices", "ComImportAttribute", s_signaturesOfComImportAttribute); @@ -559,5 +561,6 @@ static AttributeDescription() internal static readonly AttributeDescription EnumeratorCancellationAttribute = new AttributeDescription("System.Runtime.CompilerServices", "EnumeratorCancellationAttribute", s_signaturesOfEnumeratorCancellationAttribute); internal static readonly AttributeDescription SkipLocalsInitAttribute = new AttributeDescription("System.Runtime.CompilerServices", "SkipLocalsInitAttribute", s_signaturesOfSkipLocalsInitAttribute); internal static readonly AttributeDescription NativeIntegerAttribute = new AttributeDescription("System.Runtime.CompilerServices", "NativeIntegerAttribute", s_signaturesOfNativeIntegerAttribute); + internal static readonly AttributeDescription ModuleInitializerAttribute = new AttributeDescription("System.Runtime.CompilerServices", "ModuleInitializerAttribute", s_signaturesOfModuleInitializerAttribute); } } diff --git a/src/Test/Utilities/Portable/Traits/CompilerFeature.cs b/src/Test/Utilities/Portable/Traits/CompilerFeature.cs index 618e811949382..efcd371c5fd75 100644 --- a/src/Test/Utilities/Portable/Traits/CompilerFeature.cs +++ b/src/Test/Utilities/Portable/Traits/CompilerFeature.cs @@ -35,5 +35,6 @@ public enum CompilerFeature DefaultInterfaceImplementation, LambdaDiscardParameters, StatementAttributes, + ModuleInitializers, } }