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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
入れ子になった関数での名前シャドウイング
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
+
+
중첩된 함수의 이름 섀도잉
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
+
+
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
+
+
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
+
+
скрытие имен во вложенных функциях
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
+
+
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
+
+
在嵌套函数中的名称映射
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
+
+
巢狀函式中的名稱鏡像處理
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,
}
}