diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index ebb126ee94926..61cb849a9e4d7 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5314,6 +5314,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string literals or try the EXPERIMENTAL feature flag 'experimental-data-section-string-literals'. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead. diff --git a/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs b/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs index ce7045499e411..f1bcf5757fc9e 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs @@ -338,7 +338,7 @@ private void HandleReturn() private void EmitTypeReferenceToken(Cci.ITypeReference symbol, SyntaxNode syntaxNode) { - _builder.EmitToken(symbol, syntaxNode, _diagnostics.DiagnosticBag); + _builder.EmitToken(symbol, syntaxNode); } private void EmitSymbolToken(TypeSymbol symbol, SyntaxNode syntaxNode) @@ -349,18 +349,18 @@ private void EmitSymbolToken(TypeSymbol symbol, SyntaxNode syntaxNode) private void EmitSymbolToken(MethodSymbol method, SyntaxNode syntaxNode, BoundArgListOperator optArgList, bool encodeAsRawDefinitionToken = false) { var methodRef = _module.Translate(method, syntaxNode, _diagnostics.DiagnosticBag, optArgList, needDeclaration: encodeAsRawDefinitionToken); - _builder.EmitToken(methodRef, syntaxNode, _diagnostics.DiagnosticBag, encodeAsRawDefinitionToken ? Cci.MetadataWriter.RawTokenEncoding.RowId : 0); + _builder.EmitToken(methodRef, syntaxNode, encodeAsRawDefinitionToken ? Cci.MetadataWriter.RawTokenEncoding.RowId : 0); } private void EmitSymbolToken(FieldSymbol symbol, SyntaxNode syntaxNode) { var fieldRef = _module.Translate(symbol, syntaxNode, _diagnostics.DiagnosticBag); - _builder.EmitToken(fieldRef, syntaxNode, _diagnostics.DiagnosticBag); + _builder.EmitToken(fieldRef, syntaxNode); } private void EmitSignatureToken(FunctionPointerTypeSymbol symbol, SyntaxNode syntaxNode) { - _builder.EmitToken(_module.Translate(symbol).Signature, syntaxNode, _diagnostics.DiagnosticBag); + _builder.EmitToken(_module.Translate(symbol).Signature, syntaxNode); } private void EmitSequencePointStatement(BoundSequencePoint node) @@ -444,15 +444,15 @@ private void EmitRestorePreviousSequencePoint(BoundRestorePreviousSequencePoint if (_savedSequencePoints is null || !_savedSequencePoints.TryGetValue(node.Identifier, out var span)) return; - EmitStepThroughSequencePoint(node.Syntax.SyntaxTree, span); + EmitStepThroughSequencePoint(node.Syntax, span); } private void EmitStepThroughSequencePoint(BoundStepThroughSequencePoint node) { - EmitStepThroughSequencePoint(node.Syntax.SyntaxTree, node.Span); + EmitStepThroughSequencePoint(node.Syntax, node.Span); } - private void EmitStepThroughSequencePoint(SyntaxTree syntaxTree, TextSpan span) + private void EmitStepThroughSequencePoint(SyntaxNode syntaxNode, TextSpan span) { if (!_emitPdbSequencePoints) return; @@ -460,9 +460,9 @@ private void EmitStepThroughSequencePoint(SyntaxTree syntaxTree, TextSpan span) var label = new object(); // The IL builder is eager to discard unreachable code, so // we fool it by branching on a condition that is always true at runtime. - _builder.EmitConstantValue(ConstantValue.Create(true)); + _builder.EmitConstantValue(ConstantValue.Create(true), syntaxNode); _builder.EmitBranch(ILOpCode.Brtrue, label); - EmitSequencePoint(syntaxTree, span); + EmitSequencePoint(syntaxNode.SyntaxTree, span); _builder.EmitOpCode(ILOpCode.Nop); _builder.MarkLabel(label); EmitHiddenSequencePoint(); diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs index f6358956bf7d4..c5402c35d4c46 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs @@ -409,7 +409,7 @@ private void EmitArrayElementAddress(BoundArrayAccess arrayAccess, AddressKind a else { _builder.EmitArrayElementAddress(_module.Translate((ArrayTypeSymbol)arrayAccess.Expression.Type), - arrayAccess.Syntax, _diagnostics.DiagnosticBag); + arrayAccess.Syntax); } } diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitArrayInitializer.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitArrayInitializer.cs index e35d326e09bb6..ef1af66cd6730 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitArrayInitializer.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitArrayInitializer.cs @@ -55,7 +55,7 @@ private void EmitArrayInitializers(ArrayTypeSymbol arrayType, BoundArrayInitiali { ImmutableArray data = this.GetRawData(initExprs); - _builder.EmitArrayBlockInitializer(data, inits.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitArrayBlockInitializer(data, inits.Syntax); if (initializationStyle == ArrayInitializerStyle.Mixed) { @@ -245,10 +245,9 @@ private bool EnableEnumArrayBlockInitialization private ArrayInitializerStyle ShouldEmitBlockInitializer(TypeSymbol elementType, ImmutableArray inits) { - if (_module.IsEncDelta) + if (!_module.FieldRvaSupported) { - // Avoid using FieldRva table. Can be allowed if tested on all supported runtimes. - // Consider removing: https://github.com/dotnet/roslyn/issues/69480 + // Avoid using FieldRva table when not supported by the runtime. return ArrayInitializerStyle.Element; } @@ -449,10 +448,9 @@ private bool TryEmitOptimizedReadonlySpanCreation(NamedTypeSymbol spanType, Boun return true; } - if (_module.IsEncDelta) + if (!_module.FieldRvaSupported) { - // Avoid using FieldRva table. Can be allowed if tested on all supported runtimes. - // Consider removing: https://github.com/dotnet/roslyn/issues/69480 + // Avoid using FieldRva table when not supported by the runtime. return false; } @@ -556,7 +554,7 @@ private bool TryEmitOptimizedReadonlySpanCreation(NamedTypeSymbol spanType, Boun // Map a field to the block (that makes it addressable). var field = _builder.module.GetFieldForData(data, alignment: 1, wrappedExpression.Syntax, _diagnostics.DiagnosticBag); _builder.EmitOpCode(ILOpCode.Ldsflda); - _builder.EmitToken(field, wrappedExpression.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitToken(field, wrappedExpression.Syntax); _builder.EmitIntConstant(lengthForConstructor); @@ -617,7 +615,7 @@ private bool TryEmitOptimizedReadonlySpanCreation(NamedTypeSymbol spanType, Boun // call ReadOnlySpan RuntimeHelpers::CreateSpan(fldHandle) var field = _builder.module.GetFieldForData(data, alignment: (ushort)specialElementType.SizeInBytes(), wrappedExpression.Syntax, _diagnostics.DiagnosticBag); _builder.EmitOpCode(ILOpCode.Ldtoken); - _builder.EmitToken(field, wrappedExpression.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitToken(field, wrappedExpression.Syntax); _builder.EmitOpCode(ILOpCode.Call, stackAdjustment: 0); EmitSymbolToken(createSpan.Construct(elementType), wrappedExpression.Syntax, optArgList: null); return true; @@ -654,7 +652,7 @@ bool tryEmitAsCachedArrayFromBlob(NamedTypeSymbol spanType, BoundExpression wrap // T[]? array = PrivateImplementationDetails.cachingField; // if (array is not null) goto arrayNotNull; _builder.EmitOpCode(ILOpCode.Ldsfld); - _builder.EmitToken(cachingField, wrappedExpression.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitToken(cachingField, wrappedExpression.Syntax); _builder.EmitOpCode(ILOpCode.Dup); _builder.EmitBranch(ILOpCode.Brtrue, arrayNotNullLabel); @@ -665,10 +663,10 @@ bool tryEmitAsCachedArrayFromBlob(NamedTypeSymbol spanType, BoundExpression wrap _builder.EmitIntConstant(elementCount); _builder.EmitOpCode(ILOpCode.Newarr); EmitSymbolToken(arrayType.ElementType, wrappedExpression.Syntax); - _builder.EmitArrayBlockInitializer(data, wrappedExpression.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitArrayBlockInitializer(data, wrappedExpression.Syntax); _builder.EmitOpCode(ILOpCode.Dup); _builder.EmitOpCode(ILOpCode.Stsfld); - _builder.EmitToken(cachingField, wrappedExpression.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitToken(cachingField, wrappedExpression.Syntax); // arrayNotNullLabel: // new ReadOnlySpan(array) @@ -714,7 +712,7 @@ bool tryEmitAsCachedArrayOfConstants(BoundArrayCreation arrayCreation, ArrayType // T[]? array = PrivateImplementationDetails.cachingField; // if (array is not null) goto arrayNotNull; _builder.EmitOpCode(ILOpCode.Ldsfld); - _builder.EmitToken(cachingField, arrayCreation.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitToken(cachingField, arrayCreation.Syntax); _builder.EmitOpCode(ILOpCode.Dup); _builder.EmitBranch(ILOpCode.Brtrue, arrayNotNullLabel); @@ -724,7 +722,7 @@ bool tryEmitAsCachedArrayOfConstants(BoundArrayCreation arrayCreation, ArrayType EmitExpression(arrayCreation, used: true); _builder.EmitOpCode(ILOpCode.Dup); _builder.EmitOpCode(ILOpCode.Stsfld); - _builder.EmitToken(cachingField, arrayCreation.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitToken(cachingField, arrayCreation.Syntax); // arrayNotNullLabel: // new ReadOnlySpan(array) diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs index 0b8cfbc2f54b7..c1191eba65e01 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs @@ -11,11 +11,11 @@ using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.PooledObjects; using Roslyn.Utilities; using static System.Linq.ImmutableArrayExtensions; -using static Microsoft.CodeAnalysis.CSharp.Binder; namespace Microsoft.CodeAnalysis.CSharp.CodeGen { @@ -1098,7 +1098,7 @@ private void EmitArrayElementLoad(BoundArrayAccess arrayAccess, bool used) } else { - _builder.EmitArrayElementLoad(_module.Translate((ArrayTypeSymbol)arrayAccess.Expression.Type), arrayAccess.Expression.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitArrayElementLoad(_module.Translate((ArrayTypeSymbol)arrayAccess.Expression.Type), arrayAccess.Expression.Syntax); } EmitPopIfUnused(used); @@ -2382,7 +2382,7 @@ private void EmitArrayCreationExpression(BoundArrayCreation expression, bool use } else { - _builder.EmitArrayCreation(_module.Translate(arrayType), expression.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitArrayCreation(_module.Translate(arrayType), expression.Syntax); } if (expression.InitializerOpt != null) @@ -3200,7 +3200,7 @@ private void EmitArrayElementStore(ArrayTypeSymbol arrayType, SyntaxNode syntaxN } else { - _builder.EmitArrayElementStore(_module.Translate(arrayType), syntaxNode, _diagnostics.DiagnosticBag); + _builder.EmitArrayElementStore(_module.Translate(arrayType), syntaxNode); } } @@ -3438,7 +3438,7 @@ private void EmitDefaultValue(TypeSymbol type, bool used, SyntaxNode syntaxNode) var constantValue = type.GetDefaultValue(); if (constantValue != null) { - _builder.EmitConstantValue(constantValue); + _builder.EmitConstantValue(constantValue, syntaxNode); return; } } @@ -3474,44 +3474,28 @@ private void EmitDefaultExpression(BoundDefaultExpression expression, bool used) private void EmitConstantExpression(TypeSymbol type, ConstantValue constantValue, bool used, SyntaxNode syntaxNode) { - if (used) // unused constant has no side-effects + // unused constant has no side-effects + if (!used) { - // Null type parameter values must be emitted as 'initobj' rather than 'ldnull'. - if (((object)type != null) && (type.TypeKind == TypeKind.TypeParameter) && constantValue.IsNull) - { - EmitInitObj(type, used, syntaxNode); - } - else if (!TryEmitStringLiteralAsUtf8Encoded(constantValue, syntaxNode)) - { - _builder.EmitConstantValue(constantValue); - } + return; } - } - private bool TryEmitStringLiteralAsUtf8Encoded(ConstantValue constantValue, SyntaxNode syntaxNode) - { - // Emit long strings into data section so they don't overflow the UserString heap. - if (constantValue.IsString && - constantValue.StringValue.Length > _module.Compilation.DataSectionStringLiteralThreshold) + // Null type parameter values must be emitted as 'initobj' rather than 'ldnull'. + if (type is { TypeKind: TypeKind.TypeParameter } && constantValue.IsNull) { - if (Binder.GetWellKnownTypeMember(_module.Compilation, WellKnownMember.System_Text_Encoding__get_UTF8, _diagnostics, syntax: syntaxNode) == null | - Binder.GetWellKnownTypeMember(_module.Compilation, WellKnownMember.System_Text_Encoding__GetString, _diagnostics, syntax: syntaxNode) == null) - { - return false; - } - - Cci.IFieldReference field = _module.TryGetOrCreateFieldForStringValue(constantValue.StringValue, syntaxNode, _diagnostics.DiagnosticBag); - if (field == null) + EmitInitObj(type, used, syntaxNode); + } + else + { + // TODO: use-site dependencies are not reported to UsedAssemblyReferences https://github.com/dotnet/roslyn/issues/78172 + if (constantValue.IsString && constantValue.StringValue.Length > _module.Compilation.DataSectionStringLiteralThreshold) { - return false; + _ = Binder.GetWellKnownTypeMember(_module.Compilation, WellKnownMember.System_Text_Encoding__get_UTF8, _diagnostics, syntax: syntaxNode); + _ = Binder.GetWellKnownTypeMember(_module.Compilation, WellKnownMember.System_Text_Encoding__GetString, _diagnostics, syntax: syntaxNode); } - _builder.EmitOpCode(ILOpCode.Ldsfld); - _builder.EmitToken(field, syntaxNode, _diagnostics.DiagnosticBag); - return true; + _builder.EmitConstantValue(constantValue, syntaxNode); } - - return false; } private void EmitInitObj(TypeSymbol type, bool used, SyntaxNode syntaxNode) @@ -3602,7 +3586,7 @@ private void EmitHoistedVariableId(FieldSymbol field, SyntaxNode syntax) var fieldRef = _module.Translate(field, syntax, _diagnostics.DiagnosticBag, needDeclaration: true); _builder.EmitOpCode(ILOpCode.Ldtoken); - _builder.EmitToken(fieldRef, syntax, _diagnostics.DiagnosticBag, Cci.MetadataWriter.RawTokenEncoding.LiftedVariableId); + _builder.EmitToken(fieldRef, syntax, Cci.MetadataWriter.RawTokenEncoding.LiftedVariableId); } private void EmitMaximumMethodDefIndexExpression(BoundMaximumMethodDefIndex node) @@ -3628,8 +3612,7 @@ private void EmitModuleVersionIdToken(BoundModuleVersionId node) { _builder.EmitToken( _module.GetModuleVersionId(_module.Translate(node.Type, node.Syntax, _diagnostics.DiagnosticBag), node.Syntax, _diagnostics.DiagnosticBag), - node.Syntax, - _diagnostics.DiagnosticBag); + node.Syntax); } private void EmitThrowIfModuleCancellationRequested(SyntaxNode syntax) @@ -3639,8 +3622,7 @@ private void EmitThrowIfModuleCancellationRequested(SyntaxNode syntax) _builder.EmitOpCode(ILOpCode.Ldsflda); _builder.EmitToken( _module.GetModuleCancellationToken(_module.Translate(cancellationTokenType, syntax, _diagnostics.DiagnosticBag), syntax, _diagnostics.DiagnosticBag), - syntax, - _diagnostics.DiagnosticBag); + syntax); var throwMethod = (MethodSymbol)_module.Compilation.GetWellKnownTypeMember(WellKnownMember.System_Threading_CancellationToken__ThrowIfCancellationRequested); @@ -3650,8 +3632,7 @@ private void EmitThrowIfModuleCancellationRequested(SyntaxNode syntax) _builder.EmitOpCode(ILOpCode.Call, -1); _builder.EmitToken( _module.Translate(throwMethod, syntax, _diagnostics.DiagnosticBag), - syntax, - _diagnostics.DiagnosticBag); + syntax); } private void EmitModuleCancellationTokenLoad(SyntaxNode syntax) @@ -3661,8 +3642,7 @@ private void EmitModuleCancellationTokenLoad(SyntaxNode syntax) _builder.EmitOpCode(ILOpCode.Ldsfld); _builder.EmitToken( _module.GetModuleCancellationToken(_module.Translate(cancellationTokenType, syntax, _diagnostics.DiagnosticBag), syntax, _diagnostics.DiagnosticBag), - syntax, - _diagnostics.DiagnosticBag); + syntax); } private void EmitModuleVersionIdStringLoad() @@ -3685,7 +3665,7 @@ private void EmitInstrumentationPayloadRootStore(BoundInstrumentationPayloadRoot private void EmitInstrumentationPayloadRootToken(BoundInstrumentationPayloadRoot node) { - _builder.EmitToken(_module.GetInstrumentationPayloadRoot(node.AnalysisKind, _module.Translate(node.Type, node.Syntax, _diagnostics.DiagnosticBag), node.Syntax, _diagnostics.DiagnosticBag), node.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitToken(_module.GetInstrumentationPayloadRoot(node.AnalysisKind, _module.Translate(node.Type, node.Syntax, _diagnostics.DiagnosticBag), node.Syntax, _diagnostics.DiagnosticBag), node.Syntax); } private void EmitSourceDocumentIndex(BoundSourceDocumentIndex node) diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs index 8e90de620d901..87420dd579565 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs @@ -461,7 +461,7 @@ private void EmitIsNotNullOrZero(BoundExpression comparand, ConstantValue nullOr EmitBox(comparandType, comparand.Syntax); } - _builder.EmitConstantValue(nullOrZero); + _builder.EmitConstantValue(nullOrZero, comparand.Syntax); _builder.EmitOpCode(ILOpCode.Cgt_un); } @@ -475,7 +475,7 @@ private void EmitIsNullOrZero(BoundExpression comparand, ConstantValue nullOrZer EmitBox(comparandType, comparand.Syntax); } - _builder.EmitConstantValue(nullOrZero); + _builder.EmitConstantValue(nullOrZero, comparand.Syntax); _builder.EmitOpCode(ILOpCode.Ceq); } diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitStackAllocInitializer.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitStackAllocInitializer.cs index d6eadf22b4e2c..b057dfa35f650 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitStackAllocInitializer.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitStackAllocInitializer.cs @@ -59,7 +59,7 @@ private void EmitStackAlloc(TypeSymbol type, BoundArrayInitialization? inits, Bo var field = _builder.module.GetFieldForData(data, alignment: 1, inits.Syntax, _diagnostics.DiagnosticBag); _builder.EmitOpCode(ILOpCode.Dup); _builder.EmitOpCode(ILOpCode.Ldsflda); - _builder.EmitToken(field, inits.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitToken(field, inits.Syntax); _builder.EmitIntConstant(data.Length); _builder.EmitUnaligned(alignment: 1); _builder.EmitOpCode(ILOpCode.Cpblk, -3); @@ -81,10 +81,10 @@ private void EmitStackAlloc(TypeSymbol type, BoundArrayInitialization? inits, Bo // call ReadOnlySpan RuntimeHelpers::CreateSpan(fldHandle) var field = _builder.module.GetFieldForData(data, alignment: (ushort)sizeInBytes, syntaxNode, _diagnostics.DiagnosticBag); _builder.EmitOpCode(ILOpCode.Ldtoken); - _builder.EmitToken(field, syntaxNode, _diagnostics.DiagnosticBag); + _builder.EmitToken(field, syntaxNode); _builder.EmitOpCode(ILOpCode.Call, 0); var createSpanHelperReference = createSpanHelper.Construct(elementType).GetCciAdapter(); - _builder.EmitToken(createSpanHelperReference, syntaxNode, _diagnostics.DiagnosticBag); + _builder.EmitToken(createSpanHelperReference, syntaxNode); var temp = AllocateTemp(readOnlySpan, syntaxNode); _builder.EmitLocalStore(temp); @@ -128,10 +128,9 @@ void emitLocalloc() private ArrayInitializerStyle ShouldEmitBlockInitializerForStackAlloc(TypeSymbol elementType, ImmutableArray inits) { - if (_module.IsEncDelta) + if (!_module.FieldRvaSupported) { - // Avoid using FieldRva table. Can be allowed if tested on all supported runtimes. - // Consider removing: https://github.com/dotnet/roslyn/issues/69480 + // Avoid using FieldRva table when not supported by the runtime. return ArrayInitializerStyle.Element; } diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs index 107a8f02f2481..d2e30eb4e64a2 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs @@ -1096,7 +1096,7 @@ private void EmitCatchBlock(BoundCatchBlock catchBlock) var exceptionType = _module.Translate(catchBlock.ExceptionTypeOpt, catchBlock.Syntax, _diagnostics.DiagnosticBag); _builder.EmitOpCode(ILOpCode.Isinst); - _builder.EmitToken(exceptionType, catchBlock.Syntax, _diagnostics.DiagnosticBag); + _builder.EmitToken(exceptionType, catchBlock.Syntax); _builder.EmitOpCode(ILOpCode.Dup); _builder.EmitBranch(ILOpCode.Brtrue, typeCheckPassedLabel); _builder.EmitOpCode(ILOpCode.Pop); @@ -1321,7 +1321,7 @@ private void EmitSwitchHeader( } else { - _builder.EmitIntegerSwitchJumpTable(switchCaseLabels, fallThroughLabel, key, expression.Type.EnumUnderlyingTypeOrSelf().PrimitiveTypeCode); + _builder.EmitIntegerSwitchJumpTable(switchCaseLabels, fallThroughLabel, key, expression.Type.EnumUnderlyingTypeOrSelf().PrimitiveTypeCode, expression.Syntax); } if (temp != null) @@ -1408,7 +1408,10 @@ void emitLengthDispatch(LengthBasedStringSwitchData lengthBasedSwitchInfo, Local // lengthConstant -> corresponding label _builder.EmitIntegerSwitchJumpTable( lengthBasedSwitchInfo.LengthBasedJumpTable.LengthCaseLabels.Select(p => new KeyValuePair(ConstantValue.Create(p.value), p.label)).ToArray(), - fallThroughLabel, stringLength, int32Type.PrimitiveTypeCode); + fallThroughLabel, + stringLength, + int32Type.PrimitiveTypeCode, + syntaxNode); FreeTemp(stringLength); } @@ -1445,7 +1448,10 @@ void emitCharDispatches(LengthBasedStringSwitchData lengthBasedSwitchInfo, Local // charConstant -> corresponding label _builder.EmitIntegerSwitchJumpTable( charJumpTable.CharCaseLabels.Select(p => new KeyValuePair(ConstantValue.Create(p.value), p.label)).ToArray(), - fallThroughLabel, charTemp, charType.PrimitiveTypeCode); + fallThroughLabel, + charTemp, + charType.PrimitiveTypeCode, + syntaxNode); } FreeTemp(charTemp); @@ -1469,7 +1475,7 @@ void emitFinalDispatches(LengthBasedStringSwitchData lengthBasedSwitchInfo, Loca void emitMethodRef(Microsoft.Cci.IMethodReference lengthMethodRef) { var diag = DiagnosticBag.GetInstance(); - _builder.EmitToken(lengthMethodRef, syntaxNode: null, diag); + _builder.EmitToken(lengthMethodRef, syntaxNode: null); Debug.Assert(diag.IsEmptyWithoutResolution); diag.Free(); } @@ -1513,7 +1519,7 @@ private void EmitStringSwitchJumpTable( _builder.EmitLoad(key); _builder.EmitOpCode(ILOpCode.Call, stackAdjustment: 0); - _builder.EmitToken(stringHashMethodRef, syntaxNode, _diagnostics.DiagnosticBag); + _builder.EmitToken(stringHashMethodRef, syntaxNode); var UInt32Type = Binder.GetSpecialType(_module.Compilation, SpecialType.System_UInt32, syntaxNode, _diagnostics); keyHash = AllocateTemp(UInt32Type, syntaxNode); @@ -1586,7 +1592,7 @@ private void EmitStringSwitchJumpTable( // Stack: key --> length _builder.EmitOpCode(ILOpCode.Call, 0); var diag = DiagnosticBag.GetInstance(); - _builder.EmitToken(lengthMethodRef, null, diag); + _builder.EmitToken(lengthMethodRef, null); Debug.Assert(diag.IsEmptyWithoutResolution); diag.Free(); @@ -1607,6 +1613,7 @@ private void EmitStringSwitchJumpTable( }; _builder.EmitStringSwitchJumpTable( + syntaxNode, caseLabels: switchCaseLabels, fallThroughLabel: fallThroughLabel, key: key, @@ -1702,9 +1709,9 @@ private void EmitStringCompareAndBranch(LocalOrParameter key, SyntaxNode syntaxN // stackAdjustment = (pushCount - popCount) = -1 _builder.EmitLoad(key); - _builder.EmitConstantValue(stringConstant); + _builder.EmitConstantValue(stringConstant, syntaxNode); _builder.EmitOpCode(ILOpCode.Call, stackAdjustment: -1); - _builder.EmitToken(stringEqualityMethodRef, syntaxNode, _diagnostics.DiagnosticBag); + _builder.EmitToken(stringEqualityMethodRef, syntaxNode); // Branch to targetLabel if String.Equals returned true. _builder.EmitBranch(ILOpCode.Brtrue, targetLabel, ILOpCode.Brfalse); @@ -1729,11 +1736,11 @@ private void EmitCharCompareAndBranch(LocalOrParameter key, SyntaxNode syntaxNod Debug.Assert(asSpanRef != null); _builder.EmitLoad(key); - _builder.EmitConstantValue(stringConstant); + _builder.EmitConstantValue(stringConstant, syntaxNode); _builder.EmitOpCode(ILOpCode.Call, stackAdjustment: 0); - _builder.EmitToken(asSpanRef, syntaxNode, _diagnostics.DiagnosticBag); + _builder.EmitToken(asSpanRef, syntaxNode); _builder.EmitOpCode(ILOpCode.Call, stackAdjustment: -1); - _builder.EmitToken(sequenceEqualsRef, syntaxNode, _diagnostics.DiagnosticBag); + _builder.EmitToken(sequenceEqualsRef, syntaxNode); // Branch to targetLabel if SequenceEquals returned true. _builder.EmitBranch(ILOpCode.Brtrue, targetLabel, ILOpCode.Brfalse); diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs index e23c3b07ded64..8e04aaa7840d3 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs @@ -3683,7 +3683,7 @@ private void GenerateModuleInitializer(PEModuleBuilder moduleBeingBuilt, Diagnos if (_moduleInitializerMethods is object) { - var ilBuilder = new ILBuilder(moduleBeingBuilt, new LocalSlotManager(slotAllocator: null), OptimizationLevel.Release, areLocalsZeroed: false); + var ilBuilder = new ILBuilder(moduleBeingBuilt, new LocalSlotManager(slotAllocator: null), methodBodyDiagnosticBag, OptimizationLevel.Release, areLocalsZeroed: false); foreach (MethodSymbol method in _moduleInitializerMethods.OrderBy(LexicalOrderSymbolComparer.Instance)) { @@ -3691,8 +3691,7 @@ private void GenerateModuleInitializer(PEModuleBuilder moduleBeingBuilt, Diagnos ilBuilder.EmitToken( moduleBeingBuilt.Translate(method, methodBodyDiagnosticBag, needDeclaration: true), - CSharpSyntaxTree.Dummy.GetRoot(), - methodBodyDiagnosticBag); + CSharpSyntaxTree.Dummy.GetRoot()); } ilBuilder.EmitRet(isVoid: true); @@ -3778,6 +3777,7 @@ internal override EmitDifferenceResult EmitDifference( Stream metadataStream, Stream ilStream, Stream pdbStream, + EmitDifferenceOptions options, CompilationTestData? testData, CancellationToken cancellationToken) { @@ -3789,6 +3789,7 @@ internal override EmitDifferenceResult EmitDifference( metadataStream, ilStream, pdbStream, + options, testData, cancellationToken); } diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs index 1c996f88d1366..c4ebcd04da684 100644 --- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs +++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs @@ -27,17 +27,18 @@ namespace Microsoft.CodeAnalysis.CSharp { internal sealed class MethodCompiler : CSharpSymbolVisitor { +#nullable enable private readonly CSharpCompilation _compilation; private readonly bool _emittingPdb; private readonly CancellationToken _cancellationToken; private readonly BindingDiagnosticBag _diagnostics; private readonly bool _hasDeclarationErrors; private readonly bool _emitMethodBodies; - private readonly PEModuleBuilder _moduleBeingBuiltOpt; // Null if compiling for diagnostics - private readonly Predicate _filterOpt; // If not null, limit analysis to specific symbols - private readonly SynthesizedEntryPointSymbol.AsyncForwardEntryPoint _entryPointOpt; + private readonly PEModuleBuilder? _moduleBeingBuiltOpt; // Null if compiling for diagnostics + private readonly Predicate? _filterOpt; // If not null, limit analysis to specific symbols + private readonly SynthesizedEntryPointSymbol.AsyncForwardEntryPoint? _entryPointOpt; - private DebugDocumentProvider _lazyDebugDocumentProvider; + private DebugDocumentProvider? _lazyDebugDocumentProvider; // // MethodCompiler employs concurrency by following flattened fork/join pattern. @@ -54,7 +55,7 @@ internal sealed class MethodCompiler : CSharpSymbolVisitor _compilerTasks; + private ConcurrentStack? _compilerTasks; // This field tracks whether any bound method body had hasErrors set or whether any constant field had a bad value. // We track it so that we can abort emission in the event that an error occurs without a corresponding diagnostic @@ -83,8 +84,8 @@ private void SetGlobalErrorIfTrue(bool arg) } // Internal for testing only. - internal MethodCompiler(CSharpCompilation compilation, PEModuleBuilder moduleBeingBuiltOpt, bool emittingPdb, bool hasDeclarationErrors, bool emitMethodBodies, - BindingDiagnosticBag diagnostics, Predicate filterOpt, SynthesizedEntryPointSymbol.AsyncForwardEntryPoint entryPointOpt, CancellationToken cancellationToken) + internal MethodCompiler(CSharpCompilation compilation, PEModuleBuilder? moduleBeingBuiltOpt, bool emittingPdb, bool hasDeclarationErrors, bool emitMethodBodies, + BindingDiagnosticBag diagnostics, Predicate? filterOpt, SynthesizedEntryPointSymbol.AsyncForwardEntryPoint? entryPointOpt, CancellationToken cancellationToken) { Debug.Assert(compilation != null); Debug.Assert(diagnostics != null); @@ -107,12 +108,12 @@ internal MethodCompiler(CSharpCompilation compilation, PEModuleBuilder moduleBei public static void CompileMethodBodies( CSharpCompilation compilation, - PEModuleBuilder moduleBeingBuiltOpt, + PEModuleBuilder? moduleBeingBuiltOpt, bool emittingPdb, bool hasDeclarationErrors, bool emitMethodBodies, BindingDiagnosticBag diagnostics, - Predicate filterOpt, + Predicate? filterOpt, CancellationToken cancellationToken) { Debug.Assert(compilation != null); @@ -132,7 +133,7 @@ public static void CompileMethodBodies( // TODO: revise to use a loop instead of a recursion } - MethodSymbol entryPoint = null; + MethodSymbol? entryPoint = null; if (filterOpt is null) { entryPoint = GetEntryPoint(compilation, moduleBeingBuiltOpt, hasDeclarationErrors, emitMethodBodies, diagnostics, cancellationToken); @@ -182,6 +183,11 @@ public static void CompileMethodBodies( methodCompiler.WaitForWorkers(); + // Deleted definitions must be emitted before PrivateImplementationDetails are frozen since + // it may add new members to it. All changes to PrivateImplementationDetails are additions, + // so we don't need to create deleted method defs for those. + moduleBeingBuiltOpt.CreateDeletedMethodDefinitions(diagnostics.DiagnosticBag); + // all threads that were adding methods must be finished now, we can freeze the class: var privateImplClass = moduleBeingBuiltOpt.FreezePrivateImplementationDetails(); if (privateImplClass != null) @@ -197,7 +203,7 @@ public static void CompileMethodBodies( if (moduleBeingBuiltOpt != null && (methodCompiler._globalHasErrors || moduleBeingBuiltOpt.SourceModule.HasBadAttributes) && !diagnostics.HasAnyErrors() && !hasDeclarationErrors) { var messageResourceName = methodCompiler._globalHasErrors ? nameof(CodeAnalysisResources.UnableToDetermineSpecificCauseOfFailure) : nameof(CodeAnalysisResources.ModuleHasInvalidAttributes); - diagnostics.Add(ErrorCode.ERR_ModuleEmitFailure, NoLocation.Singleton, ((Cci.INamedEntity)moduleBeingBuiltOpt).Name, + diagnostics.Add(ErrorCode.ERR_ModuleEmitFailure, NoLocation.Singleton, ((Cci.INamedEntity)moduleBeingBuiltOpt).Name!, new LocalizableResourceString(messageResourceName, CodeAnalysisResources.ResourceManager, typeof(CodeAnalysisResources))); } @@ -214,7 +220,7 @@ public static void CompileMethodBodies( } } } - +#nullable disable // Returns the MethodSymbol for the assembly entrypoint. If the user has a Task returning main, // this function returns the synthesized Main MethodSymbol. internal static MethodSymbol GetEntryPoint(CSharpCompilation compilation, PEModuleBuilder moduleBeingBuilt, bool hasDeclarationErrors, bool emitMethodBodies, BindingDiagnosticBag diagnostics, CancellationToken cancellationToken) @@ -1385,6 +1391,7 @@ forSemanticModel.Syntax is { } semanticModelSyntax && } } +#nullable enable private void EmitSkeletonMethodInExtension(MethodSymbol methodSymbol) { if (!_emitMethodBodies) @@ -1392,7 +1399,10 @@ private void EmitSkeletonMethodInExtension(MethodSymbol methodSymbol) return; } - ILBuilder builder = new ILBuilder(_moduleBeingBuiltOpt, new LocalSlotManager(slotAllocator: null), OptimizationLevel.Release, areLocalsZeroed: false); + Debug.Assert(_diagnostics.DiagnosticBag != null); + Debug.Assert(_moduleBeingBuiltOpt != null); + + ILBuilder builder = new ILBuilder(_moduleBeingBuiltOpt, new LocalSlotManager(slotAllocator: null), _diagnostics.DiagnosticBag, OptimizationLevel.Release, areLocalsZeroed: false); // Emit methods in extensions as skeletons: // => throw null; @@ -1423,16 +1433,15 @@ private void EmitSkeletonMethodInExtension(MethodSymbol methodSymbol) orderedLambdaRuntimeRudeEdits: ImmutableArray.Empty, closureDebugInfo: ImmutableArray.Empty, stateMachineTypeNameOpt: null, - stateMachineHoistedLocalScopes: default(ImmutableArray), - stateMachineHoistedLocalSlots: default(ImmutableArray), - stateMachineAwaiterSlots: default(ImmutableArray), + stateMachineHoistedLocalScopes: default, + stateMachineHoistedLocalSlots: default, + stateMachineAwaiterSlots: default, StateMachineStatesDebugInfo.Create(variableSlotAllocator: null, ImmutableArray.Empty), stateMachineMoveNextDebugInfoOpt: null, codeCoverageSpans: ImmutableArray.Empty, - isPrimaryConstructor: false) - ); + isPrimaryConstructor: false)); } - +#nullable disable private static MethodSymbol GetSymbolForEmittedBody(MethodSymbol methodSymbol) { return methodSymbol.PartialDefinitionPart ?? methodSymbol; @@ -1604,9 +1613,11 @@ private static MethodBody GenerateMethodBody( var localSlotManager = new LocalSlotManager(variableSlotAllocatorOpt); var optimizations = compilation.Options.OptimizationLevel; - ILBuilder builder = new ILBuilder(moduleBuilder, localSlotManager, optimizations, method.AreLocalsZeroed); - bool hasStackalloc; var diagnosticsForThisMethod = BindingDiagnosticBag.GetInstance(withDiagnostics: true, diagnostics.AccumulatesDependencies); + Debug.Assert(diagnosticsForThisMethod.DiagnosticBag != null); + + ILBuilder builder = new ILBuilder(moduleBuilder, localSlotManager, diagnosticsForThisMethod.DiagnosticBag, optimizations, method.AreLocalsZeroed); + bool hasStackalloc; try { StateMachineMoveNextBodyDebugInfo moveNextBodyDebugInfoOpt = null; diff --git a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpSymbolMatcher.cs b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpSymbolMatcher.cs index 7e7f5a4f29ad0..c09438b4b510a 100644 --- a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpSymbolMatcher.cs +++ b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpSymbolMatcher.cs @@ -57,9 +57,17 @@ public CSharpSymbolMatcher( // For simplicity, PID helpers and no-PIA embedded definitions are not reused across generations, so we don't map them here. // Instead, new ones are regenerated as needed. - Debug.Assert(definition is PrivateImplementationDetails or Cci.IEmbeddedDefinition); + + Debug.Assert( + definition is Cci.IEmbeddedDefinition || + isPrivateImplementationDetail(definition), + $"Unexpected definition of type: {definition.GetType()}"); return null; + + static bool isPrivateImplementationDetail(Cci.IDefinition definition) + => definition is PrivateImplementationDetails || + definition is Cci.ITypeDefinitionMember { ContainingTypeDefinition: var container } && isPrivateImplementationDetail(container); } public override Cci.INamespace? MapNamespace(Cci.INamespace @namespace) diff --git a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/EmitHelpers.cs b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/EmitHelpers.cs index 020e601857447..03e2185b727f7 100644 --- a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/EmitHelpers.cs +++ b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/EmitHelpers.cs @@ -28,6 +28,7 @@ internal static EmitDifferenceResult EmitDifference( Stream metadataStream, Stream ilStream, Stream pdbStream, + EmitDifferenceOptions options, CompilationTestData? testData, CancellationToken cancellationToken) { @@ -94,6 +95,7 @@ internal static EmitDifferenceResult EmitDifference( compilation.SourceAssembly, changes, emitOptions: emitOptions, + options: options, outputKind: compilation.Options.OutputKind, serializationProperties: serializationProperties, manifestResources: manifestResources, @@ -130,7 +132,6 @@ internal static EmitDifferenceResult EmitDifference( newBaseline = compilation.SerializeToDeltaStreams( moduleBeingBuilt, definitionMap, - changes, metadataStream, ilStream, pdbStream, diff --git a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs index c565c056a507c..08e1d677504f8 100644 --- a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs @@ -25,6 +25,7 @@ internal sealed class PEDeltaAssemblyBuilder : PEAssemblyBuilderBase, IPEDeltaAs private readonly SymbolChanges _changes; private readonly CSharpSymbolMatcher.DeepTranslator _deepTranslator; private readonly MethodSymbol? _predefinedHotReloadExceptionConstructor; + private readonly EmitDifferenceOptions _options; /// /// HotReloadException type. May be created even if not used. We might find out @@ -47,6 +48,7 @@ public PEDeltaAssemblyBuilder( SourceAssemblySymbol sourceAssembly, CSharpSymbolChanges changes, EmitOptions emitOptions, + EmitDifferenceOptions options, OutputKind outputKind, Cci.ModulePropertiesForSerialization serializationProperties, IEnumerable manifestResources, @@ -54,6 +56,7 @@ public PEDeltaAssemblyBuilder( : base(sourceAssembly, emitOptions, outputKind, serializationProperties, manifestResources, additionalTypes: []) { _changes = changes; + _options = options; // Workaround for https://github.com/dotnet/roslyn/issues/3192. // When compiling state machine we stash types of awaiters and state-machine hoisted variables, @@ -74,6 +77,7 @@ public PEDeltaAssemblyBuilder( public override SymbolChanges? EncSymbolChanges => _changes; public override EmitBaseline PreviousGeneration => _changes.DefinitionMap.Baseline; + public override bool FieldRvaSupported => _options.EmitFieldRva; internal override Cci.ITypeReference EncTranslateLocalVariableType(TypeSymbol type, DiagnosticBag diagnostics) { @@ -234,7 +238,7 @@ public SynthesizedTypeMaps GetSynthesizedTypes() } public override IEnumerable GetTopLevelTypeDefinitions(EmitContext context) - => GetTopLevelTypeDefinitionsCore(context); + => GetTopLevelTypeDefinitionsExcludingNoPiaAndRootModule(context, includePrivateImplementationDetails: true); public override IEnumerable GetTopLevelSourceTypeDefinitions(EmitContext context) { diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs index 5244d968826cc..8f884e92d2e00 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs @@ -65,7 +65,7 @@ internal abstract class PEAssemblyBuilderBase : PEModuleBuilder, Cci.IAssemblyRe /// private readonly string _metadataName; #nullable enable - public PEAssemblyBuilderBase( + protected PEAssemblyBuilderBase( SourceAssemblySymbol sourceAssembly, EmitOptions emitOptions, OutputKind outputKind, @@ -654,6 +654,7 @@ internal sealed class PEAssemblyBuilder( { public override EmitBaseline? PreviousGeneration => null; public override SymbolChanges? EncSymbolChanges => null; + public override bool FieldRvaSupported => true; public override INamedTypeSymbolInternal? TryGetOrCreateSynthesizedHotReloadExceptionType() => null; diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs index 19cb20430e9bf..38f5669225f37 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs @@ -73,7 +73,7 @@ private void SetNeedsGeneratedAttributes(EmbeddableAttributes attributes) ThreadSafeFlagOperations.Set(ref _needsGeneratedAttributes, (int)attributes); } - internal PEModuleBuilder( + protected PEModuleBuilder( SourceModuleSymbol sourceModule, EmitOptions emitOptions, OutputKind outputKind, diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PENetModuleBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PENetModuleBuilder.cs index 44acf7e6ee24a..576881232a380 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PENetModuleBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PENetModuleBuilder.cs @@ -38,6 +38,7 @@ protected override void AddEmbeddedResourcesFromAddedModules(ArrayBuilder null; public override SymbolChanges? EncSymbolChanges => null; + public override bool FieldRvaSupported => true; public override INamedTypeSymbolInternal? TryGetOrCreateSynthesizedHotReloadExceptionType() => null; diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 25ba50f1a42e3..7211e43d60c83 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2408,6 +2408,8 @@ internal enum ErrorCode ERR_PPShebangInProjectBasedProgram = 9314, + ERR_TooManyUserStrings_RestartRequired = 9315, + // Note: you will need to do the following after adding errors: // 1) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs) // 2) Add message to CSharpResources.resx diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index 8a8498acc0013..278cbd4318a8a 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -1726,6 +1726,7 @@ or ErrorCode.ERR_BadAwaitInStaticVariableInitializer or ErrorCode.ERR_InvalidPathMap or ErrorCode.ERR_PublicSignButNoKey or ErrorCode.ERR_TooManyUserStrings + or ErrorCode.ERR_TooManyUserStrings_RestartRequired or ErrorCode.ERR_PeWritingFailure or ErrorCode.WRN_AttributeIgnoredWhenPublicSigning or ErrorCode.ERR_OptionMustBeAbsolutePath diff --git a/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs b/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs index ba05a944c54bd..059ec8b9672e4 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs @@ -245,6 +245,7 @@ public override void ReportDuplicateMetadataReferenceWeak(DiagnosticBag diagnost public override int ERR_MetadataNameTooLong => (int)ErrorCode.ERR_MetadataNameTooLong; public override int ERR_EncReferenceToAddedMember => (int)ErrorCode.ERR_EncReferenceToAddedMember; public override int ERR_TooManyUserStrings => (int)ErrorCode.ERR_TooManyUserStrings; + public override int ERR_TooManyUserStrings_RestartRequired => (int)ErrorCode.ERR_TooManyUserStrings_RestartRequired; public override int ERR_PeWritingFailure => (int)ErrorCode.ERR_PeWritingFailure; public override int ERR_ModuleEmitFailure => (int)ErrorCode.ERR_ModuleEmitFailure; public override int ERR_EncUpdateFailedMissingSymbol => (int)ErrorCode.ERR_EncUpdateFailedMissingSymbol; diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 7b6ef24f74a69..37ae8bfc426e4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -2397,6 +2397,11 @@ Literál nezpracovaného řetězce nezačíná dostatečným počtem uvozovek, aby bylo možné tento počet po sobě jdoucích znaků uvozovek povolit jako obsah. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. Příkazy nejvyšší úrovně se musí nacházet před obory názvů a deklaracemi typů. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index ce1baff1c7ab2..e481e2a789344 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -2397,6 +2397,11 @@ Das Rohzeichenfolgenliteral beginnt nicht mit genügend Anführungszeichen, um so viele aufeinanderfolgende Anführungszeichen als Inhalt zuzulassen. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. Anweisungen der obersten Ebene müssen vor Namespace- und Typdeklarationen stehen. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index d14f5fbc2aa2d..3dcae73e93f47 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -2397,6 +2397,11 @@ El literal de cadena sin formato no comienza con suficientes comillas para permitir tantas comillas consecutivas como contenido. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. Las instrucciones de nivel superior deben preceder a las declaraciones de espacio de nombres y de tipos. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index a0db1f39b8732..73299c0f6772f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -2397,6 +2397,11 @@ Le littéral brut de la chaîne de caractères ne commence pas par un nombre suffisant de caractères de guillemets pour autoriser un tel nombre de caractères de guillemets consécutifs comme contenu. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. Les instructions de niveau supérieur doivent précéder les déclarations d'espace de noms et de type. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 4776064d30d8f..ca9c6d183269e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -2397,6 +2397,11 @@ Il valore letterale stringa non elaborato non inizia con un numero sufficiente di virgolette per consentire questo numero di virgolette consecutive come contenuto. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. Le istruzioni di primo livello devono precedere le dichiarazioni di tipo e di spazio dei nomi. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 67daf55e4fd5a..64ffd6274eeff 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -2397,6 +2397,11 @@ 生文字列リテラルの先頭に十分な数の引用符文字がないため、連続した引用符文字をコンテンツとして使用できません。 + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. トップレベルのステートメントは、名前空間および型の宣言の前にある必要があります。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 445c283cdecb1..7c16a674e240b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -2397,6 +2397,11 @@ 원시 문자열 리터럴을 시작하는 따옴표 문자가 부족해 이렇게 많은 따옴표 문자를 콘텐츠로 사용할 수 없습니다. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. 최상위 문은 네임스페이스 및 형식 선언 앞에 와야 합니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 92320e99565ad..40a51a9d7aba7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -2397,6 +2397,11 @@ Nieprzetworzony literał ciągu nie rozpoczyna się od wystarczającej liczby znaków cudzysłowu, aby umożliwić używanie tak wielu kolejnych znaków cudzysłowu jako zawartości. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. Instrukcje najwyższego poziomu muszą poprzedzać deklaracje przestrzeni nazw i typów. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 963929d643cd1..133576185f638 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -2397,6 +2397,11 @@ A literal da cadeia de caracteres bruta não começa com caracteres de aspa suficientes para permitir esse número de caracteres de aspa consecutivos como conteúdo. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. As instruções de nível superior precisam preceder as declarações de namespace e de tipo. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index afe4e0b90bd80..30b7d953160bf 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -2397,6 +2397,11 @@ Литерал необработанной строки не начинается с достаточного количества символов кавычек, чтобы разрешить использовать такое же количество последовательных символов кавычек в качестве содержимого. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. Инструкции верхнего уровня должны предшествовать объявлениям пространств имен и типов. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 9015530c02117..2c46ca1dae051 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -2397,6 +2397,11 @@ Ham dize sabit değeri, içerik olarak bu kadar çok ardışık tırnak işareti karakterine izin vermek için yeterli sayıda tırnak işareti karakteriyle başlamıyor. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. Üst düzey deyimler ad alanı ve tür bildirimlerinden önce gelmelidir. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index d92f7af8a95a5..8ca0b9a047b72 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -2397,6 +2397,11 @@ 原始字符串字面量的开头没有足够的引号字符以允许将这么多连续的引号字符作为内容。 + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. 顶级语句必须位于命名空间和类型声明之前。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 0688757833c5b..04b102802f385 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -2397,6 +2397,11 @@ 原始字串常值開頭沒有足夠的引號字元,因此無法允許這麼多連續的引號字元做為內容。 + + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + + Top-level statements must precede namespace and type declarations. 最上層陳述式必須在命名空間和型別宣告之前。 diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EmitErrorTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EmitErrorTests.cs index d522c10deec21..0c63bf61d1e25 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/EmitErrorTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/EmitErrorTests.cs @@ -341,8 +341,12 @@ public static void Main () var expectedDiagnostics = new[] { - // error CS8103: Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string literals or try the EXPERIMENTAL feature flag 'experimental-data-section-string-literals'. - Diagnostic(ErrorCode.ERR_TooManyUserStrings).WithLocation(1, 1) + // (15,26): error CS8103: Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string literals or try the EXPERIMENTAL feature flag 'experimental-data-section-string-literals'. + // System.Console.WriteLine("J...J"); + Diagnostic(ErrorCode.ERR_TooManyUserStrings, '"' + new string('J', 1000000) + '"').WithLocation(15, 26), + // (16,26): error CS8103: Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string literals or try the EXPERIMENTAL feature flag 'experimental-data-section-string-literals'. + // System.Console.WriteLine("K...K"); + Diagnostic(ErrorCode.ERR_TooManyUserStrings, '"' + new string('K', 1000000) + '"').WithLocation(16, 26) }; CreateCompilation(source).VerifyEmitDiagnostics(expectedDiagnostics); diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EmitMetadataTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EmitMetadataTests.cs index c8577b654b471..484d3f8c0f0bc 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/EmitMetadataTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/EmitMetadataTests.cs @@ -3144,6 +3144,65 @@ .maxstack 1 Assert.Equal(0, verifier.Compilation.DataSectionStringLiteralThreshold); } + [Fact] + public void DataSectionStringLiterals_Switch() + { + var source = """ + System.Console.Write(args[0] switch + { + "a" => 1, + "bb" => 2, + "ccc" => 3, + _ => 4 + }); + """; + + var verifier = CompileAndVerify( + source, + parseOptions: TestOptions.Regular.WithFeature("experimental-data-section-string-literals", "0"), + verify: Verification.Skipped); + + verifier.VerifyIL("", """ + { + // Code size 66 (0x42) + .maxstack 2 + .locals init (int V_0, + string V_1) + IL_0000: ldarg.0 + IL_0001: ldc.i4.0 + IL_0002: ldelem.ref + IL_0003: stloc.1 + IL_0004: ldloc.1 + IL_0005: ldsfld "string .A96FAF705AF16834E6C632B61E964E1F.s" + IL_000a: call "bool string.op_Equality(string, string)" + IL_000f: brtrue.s IL_002d + IL_0011: ldloc.1 + IL_0012: ldsfld "string .DB1DE4B3DA6C7871B776D5CB968AA5A4.s" + IL_0017: call "bool string.op_Equality(string, string)" + IL_001c: brtrue.s IL_0031 + IL_001e: ldloc.1 + IL_001f: ldsfld "string .BE20CA004CC2993A396345E0D52DF013.s" + IL_0024: call "bool string.op_Equality(string, string)" + IL_0029: brtrue.s IL_0035 + IL_002b: br.s IL_0039 + IL_002d: ldc.i4.1 + IL_002e: stloc.0 + IL_002f: br.s IL_003b + IL_0031: ldc.i4.2 + IL_0032: stloc.0 + IL_0033: br.s IL_003b + IL_0035: ldc.i4.3 + IL_0036: stloc.0 + IL_0037: br.s IL_003b + IL_0039: ldc.i4.4 + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: call "void System.Console.Write(int)" + IL_0041: ret + } + """); + } + [Fact] public void DataSectionStringLiterals_InvalidUtf8() { diff --git a/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/AssemblyReferencesTests.cs b/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/AssemblyReferencesTests.cs index 7a67122fa4787..f1cd2f3208240 100644 --- a/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/AssemblyReferencesTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/AssemblyReferencesTests.cs @@ -81,9 +81,13 @@ class C compilation1.GlobalNamespace.GetMember("C").GetMember("Main")) }; - compilation1.EmitDifference(baseline, edits, s => false, mdStream, ilStream, pdbStream); + compilation1.EmitDifference(baseline, edits, s => false, mdStream, ilStream, pdbStream, EmitDifferenceOptions.Default, CancellationToken.None); - var actualIL = ImmutableArray.Create(ilStream.ToArray()).GetMethodIL(); + var il = ImmutableArray.Create(ilStream.ToArray()); + mdStream.Position = 0; + using var mdReaderProvider = MetadataReaderProvider.FromMetadataStream(mdStream); + + var actualIL = ILValidation.DumpEncDeltaMethodBodies(il, [mdReaderProvider.GetMetadataReader()]); var expectedIL = @" { // Code size 7 (0x7) @@ -153,9 +157,13 @@ class C compilation1.GlobalNamespace.GetMember("C").GetMember("Main")) }; - compilation1.EmitDifference(baseline, edits, s => false, mdStream, ilStream, pdbStream); + compilation1.EmitDifference(baseline, edits, s => false, mdStream, ilStream, pdbStream, EmitDifferenceOptions.Default, CancellationToken.None); + + var il = ImmutableArray.Create(ilStream.ToArray()); + mdStream.Position = 0; + using var mdReaderProvider = MetadataReaderProvider.FromMetadataStream(mdStream); - var actualIL = ImmutableArray.Create(ilStream.ToArray()).GetMethodIL(); + var actualIL = ILValidation.DumpEncDeltaMethodBodies(il, [mdReaderProvider.GetMetadataReader()]); // Symbol matcher should ignore overloads with missing type symbols and match // F(object). diff --git a/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueClosureTests.cs b/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueClosureTests.cs index 4f4d3c84cdba9..4b5b85deef2b2 100644 --- a/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueClosureTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueClosureTests.cs @@ -4846,6 +4846,7 @@ public void F() g.VerifyIL( """ + F { // Code size 44 (0x2c) .maxstack 2 @@ -4864,6 +4865,7 @@ .maxstack 2 IL_0026: stsfld 0x04000003 IL_002b: ret } + b__0_0 { // Code size 13 (0xd) .maxstack 8 @@ -4872,6 +4874,7 @@ .maxstack 8 IL_0007: newobj 0x06000007 IL_000c: throw } + b__0_1 { // Code size 8 (0x8) .maxstack 8 @@ -4880,6 +4883,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -4892,6 +4896,7 @@ .maxstack 8 IL_000a: stfld 0x04000004 IL_000f: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -4900,6 +4905,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__0#1 { // Code size 13 (0xd) .maxstack 8 @@ -4986,6 +4992,7 @@ public void F() g.VerifyIL( """ + F { // Code size 12 (0xc) .maxstack 2 @@ -4997,6 +5004,7 @@ .maxstack 2 IL_000a: nop IL_000b: ret } + g__L1|0_0 { // Code size 13 (0xd) .maxstack 8 @@ -5005,6 +5013,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + g__L2|0_1 { // Code size 8 (0x8) .maxstack 8 @@ -5013,6 +5022,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + g__L1|0_0#1 { // Code size 13 (0xd) .maxstack 8 @@ -5022,6 +5032,7 @@ .maxstack 8 IL_000b: nop IL_000c: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -5089,6 +5100,7 @@ public void F(int x) g.VerifyIL( """ + F { // Code size 44 (0x2c) .maxstack 2 @@ -5107,6 +5119,7 @@ .maxstack 2 IL_0026: stsfld 0x04000003 IL_002b: ret } + b__0_0 { // Code size 13 (0xd) .maxstack 8 @@ -5115,6 +5128,7 @@ .maxstack 8 IL_0007: newobj 0x06000007 IL_000c: throw } + b__0_1 { // Code size 8 (0x8) .maxstack 8 @@ -5123,6 +5137,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -5135,6 +5150,7 @@ .maxstack 8 IL_000a: stfld 0x04000004 IL_000f: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -5143,6 +5159,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__0#1 { // Code size 13 (0xd) .maxstack 8 @@ -5226,6 +5243,7 @@ public void F(int x) g.VerifyMethodDefNames("F", "g__L1|0_0", "g__L2|0_1", "g__L1|0_0#1", ".ctor"); g.VerifyIL(""" + F { // Code size 12 (0xc) .maxstack 2 @@ -5237,6 +5255,7 @@ .maxstack 2 IL_000a: nop IL_000b: ret } + g__L1|0_0 { // Code size 13 (0xd) .maxstack 8 @@ -5245,6 +5264,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + g__L2|0_1 { // Code size 8 (0x8) .maxstack 8 @@ -5253,6 +5273,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + g__L1|0_0#1 { // Code size 13 (0xd) .maxstack 8 @@ -5262,6 +5283,7 @@ .maxstack 8 IL_000b: nop IL_000c: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -5331,6 +5353,7 @@ static void F() g.VerifyIL( """ + F { // Code size 34 (0x22) .maxstack 2 @@ -5347,6 +5370,7 @@ .maxstack 2 IL_0020: stloc.0 IL_0021: ret } + b__1_0 { // Code size 31 (0x1f) .maxstack 2 @@ -5361,6 +5385,7 @@ .maxstack 2 IL_0019: call 0x06000001 IL_001e: ret } + b__1_1 { // Code size 12 (0xc) .maxstack 8 @@ -5369,6 +5394,7 @@ .maxstack 8 IL_0006: newobj 0x06000008 IL_000b: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -5381,6 +5407,7 @@ .maxstack 8 IL_000a: stfld 0x04000004 IL_000f: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -5389,6 +5416,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__1#1 { // Code size 7 (0x7) .maxstack 8 @@ -5453,6 +5481,7 @@ class C : B g.VerifyIL( """ + .ctor { // Code size 42 (0x2a) .maxstack 3 @@ -5474,6 +5503,7 @@ .maxstack 3 IL_0028: nop IL_0029: ret } + <.ctor>b__0_0 { // Code size 13 (0xd) .maxstack 8 @@ -5482,6 +5512,7 @@ .maxstack 8 IL_0007: newobj 0x06000007 IL_000c: throw } + <.ctor>b__0_1 { // Code size 12 (0xc) .maxstack 8 @@ -5490,6 +5521,7 @@ .maxstack 8 IL_0006: newobj 0x06000007 IL_000b: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -5502,6 +5534,7 @@ .maxstack 8 IL_000a: stfld 0x04000004 IL_000f: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -5510,6 +5543,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + <.ctor>b__0#1 { // Code size 7 (0x7) .maxstack 8 @@ -5517,6 +5551,7 @@ .maxstack 8 IL_0001: ldfld 0x04000005 IL_0006: ret } + <.ctor>b__1#1 { // Code size 13 (0xd) .maxstack 8 @@ -5569,6 +5604,7 @@ class B(Func f); g.VerifyIL( """ + .ctor { // Code size 33 (0x21) .maxstack 3 @@ -5585,6 +5621,7 @@ .maxstack 3 IL_001f: nop IL_0020: ret } + <.ctor>b__0_0 { // Code size 13 (0xd) .maxstack 8 @@ -5593,6 +5630,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -5605,6 +5643,7 @@ .maxstack 8 IL_000a: stfld 0x04000003 IL_000f: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -5613,6 +5652,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + <.ctor>b__0#1 { // Code size 7 (0x7) .maxstack 8 @@ -5663,6 +5703,7 @@ public void Capture_TopLevelArgs() g.VerifyIL( """ +
$ { // Code size 27 (0x1b) .maxstack 2 @@ -5677,6 +5718,7 @@ .maxstack 2 IL_0019: stloc.2 IL_001a: ret } + <
$>b__0_0 { // Code size 13 (0xd) .maxstack 8 @@ -5685,6 +5727,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -5697,6 +5740,7 @@ .maxstack 8 IL_000a: stfld 0x04000003 IL_000f: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -5705,6 +5749,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + <
$>b__0#1 { // Code size 7 (0x7) .maxstack 8 @@ -5793,6 +5838,7 @@ public void F() g.VerifyIL( """ + F { // Code size 31 (0x1f) .maxstack 8 @@ -5806,6 +5852,7 @@ .maxstack 8 IL_0019: stsfld 0x04000004 IL_001e: ret } + b__1_0 { // Code size 13 (0xd) .maxstack 8 @@ -5814,6 +5861,7 @@ .maxstack 8 IL_0007: newobj 0x06000008 IL_000c: throw } + b__1_1 { // Code size 8 (0x8) .maxstack 8 @@ -5822,6 +5870,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__1_0#1 { // Code size 13 (0xd) .maxstack 8 @@ -5831,6 +5880,7 @@ .maxstack 8 IL_000b: nop IL_000c: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -5922,6 +5972,7 @@ public void F() g.VerifyIL( """ + F { // Code size 4 (0x4) .maxstack 8 @@ -5930,6 +5981,7 @@ .maxstack 8 IL_0002: nop IL_0003: ret } + g__L1|1_0 { // Code size 13 (0xd) .maxstack 8 @@ -5938,6 +5990,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + g__L2|1_1 { // Code size 8 (0x8) .maxstack 8 @@ -5946,6 +5999,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + g__L1|1_0#1 { // Code size 13 (0xd) .maxstack 8 @@ -5955,6 +6009,7 @@ .maxstack 8 IL_000b: nop IL_000c: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -6021,6 +6076,7 @@ public void F() g.VerifyIL( """ + F { // Code size 31 (0x1f) .maxstack 8 @@ -6034,6 +6090,7 @@ .maxstack 8 IL_0019: stsfld 0x04000003 IL_001e: ret } + b__1_0 { // Code size 13 (0xd) .maxstack 8 @@ -6042,6 +6099,7 @@ .maxstack 8 IL_0007: newobj 0x06000008 IL_000c: throw } + b__1_1 { // Code size 8 (0x8) .maxstack 8 @@ -6050,6 +6108,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__1_0#1 { // Code size 13 (0xd) .maxstack 8 @@ -6059,6 +6118,7 @@ .maxstack 8 IL_000b: nop IL_000c: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -6122,6 +6182,7 @@ public void F() g.VerifyIL( """ + F { // Code size 4 (0x4) .maxstack 8 @@ -6130,6 +6191,7 @@ .maxstack 8 IL_0002: nop IL_0003: ret } + g__L1|1_0 { // Code size 13 (0xd) .maxstack 8 @@ -6138,6 +6200,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + g__L2|1_1 { // Code size 8 (0x8) .maxstack 8 @@ -6146,6 +6209,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + g__L1|1_0#1 { // Code size 13 (0xd) .maxstack 8 @@ -6155,6 +6219,7 @@ .maxstack 8 IL_000b: nop IL_000c: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -6257,6 +6322,7 @@ public void F() g.VerifyIL( """ + F { // Code size 35 (0x23) .maxstack 2 @@ -6275,6 +6341,7 @@ .maxstack 2 IL_0021: nop IL_0022: ret } + b__0 { // Code size 7 (0x7) .maxstack 8 @@ -6356,6 +6423,7 @@ public void F() g.VerifyIL( """ + F { // Code size 13 (0xd) .maxstack 2 @@ -6368,6 +6436,7 @@ .maxstack 2 IL_000b: nop IL_000c: ret } + g__L|0_0 { // Code size 7 (0x7) .maxstack 8 @@ -6427,6 +6496,7 @@ public void F() g.VerifyIL( """ + F { // Code size 32 (0x20) .maxstack 2 @@ -6441,6 +6511,7 @@ .maxstack 2 IL_001a: stsfld 0x04000004 IL_001f: ret } + b__0 { // Code size 13 (0xd) .maxstack 8 @@ -6449,6 +6520,7 @@ .maxstack 8 IL_0007: newobj 0x06000005 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -6461,6 +6533,7 @@ .maxstack 8 IL_000a: stfld 0x04000002 IL_000f: ret } + .cctor { // Code size 11 (0xb) .maxstack 8 @@ -6468,6 +6541,7 @@ .maxstack 8 IL_0005: stsfld 0x04000003 IL_000a: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -6476,6 +6550,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__0_0#1 { // Code size 8 (0x8) .maxstack 8 @@ -6518,6 +6593,7 @@ public void F() g.VerifyIL( """ + F { // Code size 16 (0x10) .maxstack 2 @@ -6530,6 +6606,7 @@ .maxstack 2 IL_000e: nop IL_000f: ret } + b__0_0#1 { // Code size 12 (0xc) .maxstack 8 @@ -6538,6 +6615,7 @@ .maxstack 8 IL_0006: newobj 0x06000005 IL_000b: throw } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -6546,6 +6624,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__0#2 { // Code size 15 (0xf) .maxstack 8 @@ -6643,6 +6722,7 @@ public void F() g.VerifyIL( """ + F { // Code size 14 (0xe) .maxstack 1 @@ -6661,6 +6741,7 @@ .maxstack 1 IL_000c: nop IL_000d: ret } + g__L|0_0 { // Code size 13 (0xd) .maxstack 8 @@ -6669,6 +6750,7 @@ .maxstack 8 IL_0007: newobj 0x06000007 IL_000c: throw } + g__L|0_1 { // Code size 12 (0xc) .maxstack 8 @@ -6677,6 +6759,7 @@ .maxstack 8 IL_0006: newobj 0x06000007 IL_000b: throw } + g__L|0_0#1 { // Code size 8 (0x8) .maxstack 8 @@ -6685,6 +6768,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + g__L|0_1#1 { // Code size 8 (0x8) .maxstack 8 @@ -6693,6 +6777,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -6807,6 +6892,7 @@ public void F() g.VerifyIL( """ + F { // Code size 58 (0x3a) .maxstack 8 @@ -6825,6 +6911,7 @@ .maxstack 8 IL_0034: stsfld 0x04000003 IL_0039: ret } + b__1_0 { // Code size 13 (0xd) .maxstack 8 @@ -6833,6 +6920,7 @@ .maxstack 8 IL_0007: newobj 0x06000007 IL_000c: throw } + b__1_1 { // Code size 8 (0x8) .maxstack 8 @@ -6841,6 +6929,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -6853,6 +6942,7 @@ .maxstack 8 IL_000a: stfld 0x04000004 IL_000f: ret } + b__1_0#1 { // Code size 8 (0x8) .maxstack 8 @@ -6959,6 +7049,7 @@ public void F() g.VerifyIL( """ + F { // Code size 4 (0x4) .maxstack 8 @@ -6967,6 +7058,7 @@ .maxstack 8 IL_0002: nop IL_0003: ret } + g__L1|1_0 { // Code size 13 (0xd) .maxstack 8 @@ -6975,6 +7067,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + g__L2|1_1 { // Code size 8 (0x8) .maxstack 8 @@ -6983,6 +7076,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + g__L1|1_0#1 { // Code size 8 (0x8) .maxstack 8 @@ -6991,6 +7085,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -7056,6 +7151,7 @@ public void F() g.VerifyIL( """ + F { // Code size 16 (0x10) .maxstack 2 @@ -7068,6 +7164,7 @@ .maxstack 2 IL_000e: nop IL_000f: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -7076,6 +7173,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__0#1 { // Code size 13 (0xd) .maxstack 8 @@ -7116,6 +7214,7 @@ public void F() g.VerifyMethodDefNames("F", "b__0#1", ".ctor"); g.VerifyIL(""" + F { // Code size 4 (0x4) .maxstack 1 @@ -7124,6 +7223,7 @@ .maxstack 1 IL_0002: stloc.2 IL_0003: ret } + b__0#1 { // Code size 12 (0xc) .maxstack 8 @@ -7132,6 +7232,7 @@ .maxstack 8 IL_0006: newobj 0x06000005 IL_000b: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -7195,6 +7296,7 @@ public void F() g.VerifyIL( """ + F { // Code size 11 (0xb) .maxstack 2 @@ -7205,6 +7307,7 @@ .maxstack 2 IL_0009: nop IL_000a: ret } + g__L|0#1_0#1 { // Code size 13 (0xd) .maxstack 8 @@ -7242,6 +7345,7 @@ public void F() g.VerifyMethodDefNames("F", "g__L|0#1_0#1", ".ctor"); g.VerifyIL(""" + F { // Code size 4 (0x4) .maxstack 1 @@ -7250,6 +7354,7 @@ .maxstack 1 IL_0002: stloc.2 IL_0003: ret } + g__L|0#1_0#1 { // Code size 12 (0xc) .maxstack 8 @@ -7258,6 +7363,7 @@ .maxstack 8 IL_0006: newobj 0x06000004 IL_000b: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -7360,6 +7466,7 @@ void F() g.VerifyIL( """ + F { // Code size 82 (0x52) .maxstack 3 @@ -7396,6 +7503,7 @@ .maxstack 3 IL_0050: nop IL_0051: ret } + b__0 { // Code size 7 (0x7) .maxstack 8 @@ -7403,6 +7511,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + b__1 { // Code size 12 (0xc) .maxstack 8 @@ -7411,6 +7520,7 @@ .maxstack 8 IL_0006: newobj 0x06000008 IL_000b: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -7423,6 +7533,7 @@ .maxstack 8 IL_000a: stfld 0x04000003 IL_000f: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -7431,6 +7542,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__1#1 { // Code size 19 (0x13) .maxstack 8 @@ -7552,6 +7664,7 @@ void F() g.VerifyIL( """ + F { // Code size 24 (0x18) .maxstack 2 @@ -7570,6 +7683,7 @@ .maxstack 2 IL_0016: nop IL_0017: ret } + g__L1|0_0 { // Code size 7 (0x7) .maxstack 8 @@ -7577,6 +7691,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + g__L2|0_1 { // Code size 12 (0xc) .maxstack 8 @@ -7585,6 +7700,7 @@ .maxstack 8 IL_0006: newobj 0x06000006 IL_000b: throw } + g__L2|0_1#1 { // Code size 14 (0xe) .maxstack 8 @@ -7595,6 +7711,7 @@ .maxstack 8 IL_000c: add IL_000d: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -7698,6 +7815,7 @@ void F() g.VerifyIL( """ + F { // Code size 68 (0x44) .maxstack 2 @@ -7728,6 +7846,7 @@ .maxstack 2 IL_0042: nop IL_0043: ret } + b__0 { // Code size 7 (0x7) .maxstack 8 @@ -7735,6 +7854,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + b__1 { // Code size 12 (0xc) .maxstack 8 @@ -7743,6 +7863,7 @@ .maxstack 8 IL_0006: newobj 0x06000008 IL_000b: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -7755,6 +7876,7 @@ .maxstack 8 IL_000a: stfld 0x04000004 IL_000f: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -7763,6 +7885,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__1#1 { // Code size 7 (0x7) .maxstack 8 @@ -7883,6 +8006,7 @@ void F() g.VerifyIL( """ + F { // Code size 24 (0x18) .maxstack 2 @@ -7901,6 +8025,7 @@ .maxstack 2 IL_0016: nop IL_0017: ret } + g__L1|0_0 { // Code size 7 (0x7) .maxstack 8 @@ -7908,6 +8033,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + g__L2|0_1 { // Code size 12 (0xc) .maxstack 8 @@ -7916,6 +8042,7 @@ .maxstack 8 IL_0006: newobj 0x06000006 IL_000b: throw } + g__L2|0_1#1 { // Code size 7 (0x7) .maxstack 8 @@ -7923,6 +8050,7 @@ .maxstack 8 IL_0001: ldfld 0x04000002 IL_0006: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -8019,6 +8147,7 @@ void F() "b__2#1"); g.VerifyIL(""" + F { // Code size 131 (0x83) .maxstack 2 @@ -8069,6 +8198,7 @@ .maxstack 2 IL_0081: nop IL_0082: ret } + b__0 { // Code size 7 (0x7) .maxstack 8 @@ -8076,6 +8206,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + b__1 { // Code size 12 (0xc) .maxstack 8 @@ -8084,6 +8215,7 @@ .maxstack 8 IL_0006: newobj 0x06000008 IL_000b: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -8096,6 +8228,7 @@ .maxstack 8 IL_000a: stfld 0x04000004 IL_000f: ret } + .ctor, .ctor { // Code size 8 (0x8) .maxstack 8 @@ -8104,6 +8237,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__1#1 { // Code size 24 (0x18) .maxstack 8 @@ -8116,6 +8250,7 @@ .maxstack 8 IL_0016: add IL_0017: ret } + b__2#1 { // Code size 36 (0x24) .maxstack 8 @@ -8249,6 +8384,7 @@ void F() g.VerifyMethodDefNames("F", "g__L1|0_0", "g__L2|0_1", "g__L3|0_2#1"); g.VerifyIL(""" + F { // Code size 35 (0x23) .maxstack 2 @@ -8273,6 +8409,7 @@ .maxstack 2 IL_0021: nop IL_0022: ret } + g__L1|0_0 { // Code size 7 (0x7) .maxstack 8 @@ -8280,6 +8417,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + g__L2|0_1 { // Code size 14 (0xe) .maxstack 8 @@ -8290,6 +8428,7 @@ .maxstack 8 IL_000c: add IL_000d: ret } + g__L3|0_2#1 { // Code size 21 (0x15) .maxstack 8 @@ -8427,6 +8566,7 @@ public void F() g.VerifyIL( """ + F { // Code size 84 (0x54) .maxstack 2 @@ -8460,6 +8600,7 @@ .maxstack 2 IL_0052: nop IL_0053: ret } + b__0 { // Code size 7 (0x7) .maxstack 8 @@ -8467,6 +8608,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + b__2 { // Code size 12 (0xc) .maxstack 8 @@ -8475,6 +8617,7 @@ .maxstack 8 IL_0006: newobj 0x06000009 IL_000b: throw } + b__1 { // Code size 7 (0x7) .maxstack 8 @@ -8482,6 +8625,7 @@ .maxstack 8 IL_0001: ldfld 0x04000002 IL_0006: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -8494,6 +8638,7 @@ .maxstack 8 IL_000a: stfld 0x04000003 IL_000f: ret } + b__2#1 { // Code size 9 (0x9) .maxstack 8 @@ -8625,6 +8770,7 @@ public void F() g.VerifyIL( """ + F { // Code size 23 (0x17) .maxstack 2 @@ -8642,6 +8788,7 @@ .maxstack 2 IL_0015: nop IL_0016: ret } + g__L1|0_0 { // Code size 7 (0x7) .maxstack 8 @@ -8649,6 +8796,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + g__L2|0_1 { // Code size 7 (0x7) .maxstack 8 @@ -8656,6 +8804,7 @@ .maxstack 8 IL_0001: ldfld 0x04000002 IL_0006: ret } + g__L3|0_2 { // Code size 12 (0xc) .maxstack 8 @@ -8664,6 +8813,7 @@ .maxstack 8 IL_0006: newobj 0x06000007 IL_000b: throw } + g__L3|0_2#1 { // Code size 9 (0x9) .maxstack 8 @@ -8673,6 +8823,7 @@ .maxstack 8 IL_0007: add IL_0008: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -8789,6 +8940,7 @@ public void F() g.VerifyIL( """ + F { // Code size 62 (0x3e) .maxstack 2 @@ -8816,6 +8968,7 @@ .maxstack 2 IL_003c: nop IL_003d: ret } + g__L1|0 { // Code size 13 (0xd) .maxstack 8 @@ -8824,6 +8977,7 @@ .maxstack 8 IL_0007: newobj 0x0600000A IL_000c: throw } + b__2 { // Code size 12 (0xc) .maxstack 8 @@ -8832,6 +8986,7 @@ .maxstack 8 IL_0006: newobj 0x0600000A IL_000b: throw } + b__1 { // Code size 7 (0x7) .maxstack 8 @@ -8839,6 +8994,7 @@ .maxstack 8 IL_0001: ldfld 0x04000002 IL_0006: ret } + g__L1|1_0#1 { // Code size 7 (0x7) .maxstack 8 @@ -8846,6 +9002,7 @@ .maxstack 8 IL_0001: ldfld 0x04000004 IL_0006: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -8858,6 +9015,7 @@ .maxstack 8 IL_000a: stfld 0x04000003 IL_000f: ret } + b__2#1 { // Code size 9 (0x9) .maxstack 8 @@ -8990,6 +9148,7 @@ public void F() g.VerifyMethodDefNames("F", "g__L1|1_0", "g__L3|1_2", "b__1", ".ctor", "g__L3|2#1"); g.VerifyIL(""" + F { // Code size 45 (0x2d) .maxstack 2 @@ -9013,6 +9172,7 @@ .maxstack 2 IL_002b: nop IL_002c: ret } + g__L1|1_0 { // Code size 7 (0x7) .maxstack 8 @@ -9020,6 +9180,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + g__L3|1_2 { // Code size 12 (0xc) .maxstack 8 @@ -9028,6 +9189,7 @@ .maxstack 8 IL_0006: newobj 0x06000008 IL_000b: throw } + b__1 { // Code size 7 (0x7) .maxstack 8 @@ -9035,6 +9197,7 @@ .maxstack 8 IL_0001: ldfld 0x04000002 IL_0006: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -9047,6 +9210,7 @@ .maxstack 8 IL_000a: stfld 0x04000003 IL_000f: ret } + g__L3|2#1 { // Code size 9 (0x9) .maxstack 8 @@ -9128,6 +9292,7 @@ public void F() g.VerifyIL( """ + F { // Code size 40 (0x28) .maxstack 2 @@ -9147,6 +9312,7 @@ .maxstack 2 IL_0026: nop IL_0027: ret } + b__0 { // Code size 14 (0xe) .maxstack 8 @@ -9224,6 +9390,7 @@ public void F() g.VerifyMethodDefNames("F", "g__L|0_0", "g__L|0_0#1", ".ctor"); g.VerifyIL(""" + F { // Code size 19 (0x13) .maxstack 2 @@ -9237,6 +9404,7 @@ .maxstack 2 IL_0011: nop IL_0012: ret } + g__L|0_0 { // Code size 13 (0xd) .maxstack 8 @@ -9245,6 +9413,7 @@ .maxstack 8 IL_0007: newobj 0x06000005 IL_000c: throw } + g__L|0_0#1 { // Code size 14 (0xe) .maxstack 8 @@ -9255,6 +9424,7 @@ .maxstack 8 IL_000c: add IL_000d: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -9342,6 +9512,7 @@ public void F() g.VerifyIL( """ + F { // Code size 40 (0x28) .maxstack 2 @@ -9361,6 +9532,7 @@ .maxstack 2 IL_0026: nop IL_0027: ret } + b__0 { // Code size 14 (0xe) .maxstack 8 @@ -9442,6 +9614,7 @@ public void F() g.VerifyIL( """ + F { // Code size 11 (0xb) .maxstack 2 @@ -9452,6 +9625,7 @@ .maxstack 2 IL_0009: nop IL_000a: ret } + g__L|0 { // Code size 13 (0xd) .maxstack 8 @@ -9460,6 +9634,7 @@ .maxstack 8 IL_0007: newobj 0x06000008 IL_000c: throw } + b__1 { // Code size 12 (0xc) .maxstack 8 @@ -9468,6 +9643,7 @@ .maxstack 8 IL_0006: newobj 0x06000008 IL_000b: throw } + g__L|1_0#1 { // Code size 7 (0x7) .maxstack 8 @@ -9475,6 +9651,7 @@ .maxstack 8 IL_0001: ldfld 0x04000003 IL_0006: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -9573,6 +9750,7 @@ public void F() g.VerifyIL( """ + F { // Code size 11 (0xb) .maxstack 2 @@ -9583,6 +9761,7 @@ .maxstack 2 IL_0009: nop IL_000a: ret } + g__L|0 { // Code size 13 (0xd) .maxstack 8 @@ -9591,6 +9770,7 @@ .maxstack 8 IL_0007: newobj 0x06000007 IL_000c: throw } + g__L|1_0#1 { // Code size 7 (0x7) .maxstack 8 @@ -9598,6 +9778,7 @@ .maxstack 8 IL_0001: ldfld 0x04000003 IL_0006: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -9676,6 +9857,7 @@ public void F() g.VerifyMethodDefNames("F", "g__L|1_0", ".ctor", ".ctor", "g__L|0#1", "b__1#1"); g.VerifyIL(""" + F { // Code size 34 (0x22) .maxstack 2 @@ -9693,6 +9875,7 @@ .maxstack 2 IL_0020: nop IL_0021: ret } + g__L|1_0 { // Code size 13 (0xd) .maxstack 8 @@ -9701,6 +9884,7 @@ .maxstack 8 IL_0007: newobj 0x06000005 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -9713,6 +9897,7 @@ .maxstack 8 IL_000a: stfld 0x04000002 IL_000f: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -9721,6 +9906,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + g__L|0#1, b__1#1 { // Code size 7 (0x7) .maxstack 8 @@ -9794,7 +9980,8 @@ public void F() g.VerifyIL( """ - { + F + { // Code size 34 (0x22) .maxstack 2 IL_0000: newobj 0x06000006 @@ -9811,6 +9998,7 @@ .maxstack 2 IL_0020: nop IL_0021: ret } + g__L|1_0 { // Code size 13 (0xd) .maxstack 8 @@ -9819,6 +10007,7 @@ .maxstack 8 IL_0007: newobj 0x06000005 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -9831,6 +10020,7 @@ .maxstack 8 IL_000a: stfld 0x04000002 IL_000f: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -9839,6 +10029,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + g__L|0#1 { // Code size 7 (0x7) .maxstack 8 @@ -9906,6 +10097,7 @@ public void F() g.VerifyIL( """ + F { // Code size 30 (0x1e) .maxstack 8 @@ -9918,6 +10110,7 @@ .maxstack 8 IL_0018: stsfld 0x04000004 IL_001d: ret } + b__0_0 { // Code size 16 (0x10) .maxstack 8 @@ -9926,6 +10119,7 @@ .maxstack 8 IL_000a: newobj 0x06000006 IL_000f: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -9938,6 +10132,7 @@ .maxstack 8 IL_000a: stfld 0x04000003 IL_000f: ret } + b__0_0#1 { // Code size 10 (0xa) .maxstack 8 diff --git a/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueTests.cs b/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueTests.cs index cadd2d351b7b7..52fb9f8a63973 100644 --- a/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueTests.cs @@ -11,6 +11,8 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; +using System.Text; +using System.Threading; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; @@ -100,7 +102,8 @@ public C() Handle(4, TableIndex.CustomAttribute) }); - var expectedIL = """ + g.VerifyIL(""" + .ctor { // Code size 13 (0xd) .maxstack 8 @@ -109,6 +112,7 @@ .maxstack 8 IL_0007: newobj 0x06000003 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -121,10 +125,7 @@ .maxstack 8 IL_000a: stfld 0x04000001 IL_000f: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .Verify(); } @@ -186,6 +187,7 @@ class C }); g.VerifyIL(""" + .ctor { // Code size 13 (0xd) .maxstack 8 @@ -194,6 +196,7 @@ .maxstack 8 IL_0007: newobj 0x06000003 IL_000c: throw } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -202,6 +205,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -2324,6 +2328,7 @@ void F() }); g.VerifyIL(""" + F { // Code size 30 (0x1e) .maxstack 8 @@ -2336,6 +2341,7 @@ .maxstack 8 IL_0018: stsfld 0x04000003 IL_001d: ret } + b__0_0 { // Code size 12 (0xc) .maxstack 8 @@ -2344,6 +2350,7 @@ .maxstack 8 IL_0006: newobj 0x06000007 IL_000b: throw } + b__0_1 { // Code size 8 (0x8) .maxstack 8 @@ -2352,6 +2359,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -2664,6 +2672,7 @@ partial void M() g.VerifyMethodDefNames("M", "b__0", ".ctor", ".ctor", "b__0#1"); g.VerifyIL(""" + M { // Code size 28 (0x1c) .maxstack 2 @@ -2679,6 +2688,7 @@ .maxstack 2 IL_001a: stloc.1 IL_001b: ret } + b__0 { // Code size 12 (0xc) .maxstack 8 @@ -2687,6 +2697,7 @@ .maxstack 8 IL_0006: newobj 0x06000005 IL_000b: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -2699,6 +2710,7 @@ .maxstack 8 IL_000a: stfld 0x04000002 IL_000f: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -2707,6 +2719,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__0#1 { // Code size 9 (0x9) .maxstack 8 @@ -3991,6 +4004,7 @@ class C }) .AddGeneration( + // 1 source: """ class C { @@ -4031,6 +4045,7 @@ class C }); g.VerifyIL(""" + get_P, set_P { // Code size 13 (0xd) .maxstack 8 @@ -4039,6 +4054,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -4054,6 +4070,7 @@ .maxstack 8 """); }) .AddGeneration( + // 2 source: """ class C { @@ -4090,7 +4107,8 @@ class C Handle(4, TableIndex.MethodSemantics), }); - var expectedIL = """ + g.VerifyIL(""" + get_P { // Code size 7 (0x7) .maxstack 8 @@ -4098,6 +4116,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + set_P { // Code size 8 (0x8) .maxstack 8 @@ -4106,10 +4125,7 @@ .maxstack 8 IL_0002: stfld 0x04000001 IL_0007: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .Verify(); } @@ -4133,6 +4149,7 @@ class C }) .AddGeneration( + // 1 source: """ class C { @@ -4175,6 +4192,7 @@ class C ]); g.VerifyIL(""" + get_P, set_P { // Code size 13 (0xd) .maxstack 8 @@ -4183,6 +4201,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -4198,6 +4217,7 @@ .maxstack 8 """); }) .AddGeneration( + // 2 source: """ class C { @@ -4243,7 +4263,8 @@ class C Handle(4, TableIndex.MethodSemantics) ]); - var expectedIL = """ + g.VerifyIL(""" + get_P { // Code size 7 (0x7) .maxstack 8 @@ -4251,6 +4272,7 @@ .maxstack 8 IL_0001: ldfld 0x04000002 IL_0006: ret } + set_P { // Code size 8 (0x8) .maxstack 8 @@ -4259,10 +4281,7 @@ .maxstack 8 IL_0002: stfld 0x04000002 IL_0007: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .Verify(); } @@ -4324,6 +4343,7 @@ class C }); g.VerifyIL(""" + get_P, set_P { // Code size 13 (0xd) .maxstack 8 @@ -4332,6 +4352,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -4386,6 +4407,7 @@ class C }); g.VerifyIL(""" + get_P { // Code size 11 (0xb) .maxstack 1 @@ -4396,6 +4418,7 @@ .maxstack 1 IL_0009: ldloc.0 IL_000a: ret } + set_P { // Code size 2 (0x2) .maxstack 8 @@ -4460,6 +4483,7 @@ class C }); g.VerifyIL(""" + set_P { // Code size 13 (0xd) .maxstack 8 @@ -4468,6 +4492,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -4521,6 +4546,7 @@ class C }); g.VerifyIL(""" + get_P { // Code size 11 (0xb) .maxstack 1 @@ -4531,6 +4557,7 @@ .maxstack 1 IL_0009: ldloc.0 IL_000a: ret } + set_P { // Code size 2 (0x2) .maxstack 8 @@ -4607,6 +4634,7 @@ class C ]); var expectedIL = """ + get_P { // Code size 7 (0x7) .maxstack 8 @@ -4614,6 +4642,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + set_P { // Code size 8 (0x8) .maxstack 8 @@ -4692,6 +4721,7 @@ class C ]); var expectedIL = """ + get_P { // Code size 7 (0x7) .maxstack 8 @@ -4699,6 +4729,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + set_P { // Code size 8 (0x8) .maxstack 8 @@ -4772,6 +4803,7 @@ class C ]); var expectedIL = """ + get_P { // Code size 7 (0x7) .maxstack 8 @@ -4779,6 +4811,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + set_P { // Code size 8 (0x8) .maxstack 8 @@ -4881,7 +4914,8 @@ class C Handle(4, TableIndex.MethodSemantics) }); - var expectedIL = """ + g.VerifyIL(""" + get_P, set_P { // Code size 13 (0xd) .maxstack 8 @@ -4890,6 +4924,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + get_P { // Code size 7 (0x7) .maxstack 8 @@ -4897,6 +4932,7 @@ .maxstack 8 IL_0001: ldfld 0x04000002 IL_0006: ret } + set_P { // Code size 8 (0x8) .maxstack 8 @@ -4905,6 +4941,7 @@ .maxstack 8 IL_0002: stfld 0x04000002 IL_0007: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -4917,10 +4954,7 @@ .maxstack 8 IL_000a: stfld 0x04000003 IL_000f: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .AddGeneration( // 2 @@ -4972,6 +5006,7 @@ class C }); g.VerifyIL(""" + get_P { // Code size 7 (0x7) .maxstack 8 @@ -4979,6 +5014,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + set_P { // Code size 8 (0x8) .maxstack 8 @@ -4987,6 +5023,7 @@ .maxstack 8 IL_0002: stfld 0x04000001 IL_0007: ret } + get_P, set_P { // Code size 13 (0xd) .maxstack 8 @@ -5087,6 +5124,7 @@ class C }); g.VerifyIL(""" + get_P, set_P { // Code size 13 (0xd) .maxstack 8 @@ -5095,6 +5133,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + get_Q { // Code size 7 (0x7) .maxstack 8 @@ -5102,6 +5141,7 @@ .maxstack 8 IL_0001: ldfld 0x04000002 IL_0006: ret } + set_Q { // Code size 8 (0x8) .maxstack 8 @@ -5110,6 +5150,7 @@ .maxstack 8 IL_0002: stfld 0x04000002 IL_0007: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -5174,6 +5215,7 @@ class C }); g.VerifyIL(""" + get_P { // Code size 7 (0x7) .maxstack 8 @@ -5181,6 +5223,7 @@ .maxstack 8 IL_0001: ldfld 0x04000001 IL_0006: ret } + set_P { // Code size 8 (0x8) .maxstack 8 @@ -5189,6 +5232,7 @@ .maxstack 8 IL_0002: stfld 0x04000001 IL_0007: ret } + get_Q, set_Q { // Code size 13 (0xd) .maxstack 8 @@ -5260,6 +5304,7 @@ class C }); g.VerifyIL(""" + get_Item, set_Item { // Code size 13 (0xd) .maxstack 8 @@ -5268,6 +5313,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -5354,7 +5400,8 @@ class C }); g.VerifyIL(""" - { + get_Item + { // Code size 13 (0xd) .maxstack 8 IL_0000: ldstr 0x70000005 @@ -5362,6 +5409,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + get_Item { // Code size 7 (0x7) .maxstack 1 @@ -5372,6 +5420,7 @@ .maxstack 1 IL_0005: ldloc.0 IL_0006: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -5426,6 +5475,7 @@ class C }); g.VerifyIL(""" + get_Item { // Code size 7 (0x7) .maxstack 1 @@ -5436,6 +5486,7 @@ .maxstack 1 IL_0005: ldloc.0 IL_0006: ret } + get_Item { // Code size 13 (0xd) .maxstack 8 @@ -5485,6 +5536,7 @@ class C }); g.VerifyIL(""" + get_Item { // Code size 7 (0x7) .maxstack 1 @@ -5553,12 +5605,14 @@ class C }); g.VerifyIL(""" + get_Item { // Code size 2 (0x2) .maxstack 8 IL_0000: ldc.i4.1 IL_0001: ret } + set_Item { // Code size 2 (0x2) .maxstack 8 @@ -5767,6 +5821,7 @@ class C }); g.VerifyIL(""" + add_E, remove_E { // Code size 13 (0xd) .maxstack 8 @@ -5775,6 +5830,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -5883,6 +5939,7 @@ class C }); g.VerifyIL(""" + add_E, remove_E { // Code size 13 (0xd) .maxstack 8 @@ -5891,6 +5948,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + add_F { // Code size 41 (0x29) .maxstack 3 @@ -5915,6 +5973,7 @@ .maxstack 3 IL_0026: bne.un.s IL_0007 IL_0028: ret } + remove_F { // Code size 41 (0x29) .maxstack 3 @@ -5939,6 +5998,7 @@ .maxstack 3 IL_0026: bne.un.s IL_0007 IL_0028: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -6006,6 +6066,7 @@ class C }); g.VerifyIL(""" + add_E { // Code size 41 (0x29) .maxstack 3 @@ -6030,6 +6091,7 @@ .maxstack 3 IL_0026: bne.un.s IL_0007 IL_0028: ret } + remove_E { // Code size 41 (0x29) .maxstack 3 @@ -6054,6 +6116,7 @@ .maxstack 3 IL_0026: bne.un.s IL_0007 IL_0028: ret } + add_F, remove_F { // Code size 13 (0xd) .maxstack 8 @@ -12190,7 +12253,8 @@ class C Handle(4, TableIndex.CustomAttribute) ]); - var expectedIL = """ + g.VerifyIL(""" + op_LogicalNot { // Code size 13 (0xd) .maxstack 8 @@ -12199,6 +12263,7 @@ .maxstack 8 IL_0007: newobj 0x06000003 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -12211,10 +12276,7 @@ .maxstack 8 IL_000a: stfld 0x04000001 IL_000f: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .Verify(); } @@ -12447,8 +12509,9 @@ static string F() badStream, ilStream, pdbStream, + EmitDifferenceOptions.Default, new CompilationTestData(), - default); + CancellationToken.None); Assert.False(result.Success); result.Diagnostics.Verify( // error CS8104: An error occurred while writing the output file: System.IO.IOException: I/O error occurred. @@ -12462,8 +12525,9 @@ static string F() mdStream, badStream, pdbStream, + EmitDifferenceOptions.Default, new CompilationTestData(), - default); + CancellationToken.None); Assert.False(result.Success); result.Diagnostics.Verify( // error CS8104: An error occurred while writing the output file: System.IO.IOException: I/O error occurred. @@ -12477,8 +12541,9 @@ static string F() mdStream, ilStream, badStream, + EmitDifferenceOptions.Default, new CompilationTestData(), - default); + CancellationToken.None); Assert.False(result.Success); result.Diagnostics.Verify( // error CS0041: Unexpected error writing debug information -- 'I/O error occurred.' @@ -12532,8 +12597,9 @@ static string F() mdStream, ilStream, badStream, + EmitDifferenceOptions.Default, new CompilationTestData(), - default); + CancellationToken.None); Assert.False(result.Success); result.Diagnostics.Verify( // error CS0041: Unexpected error writing debug information -- 'I/O error occurred.' @@ -15990,6 +16056,7 @@ public void Records_AddPrimaryConstructorParameter() }); g.VerifyIL(""" + .ctor { // Code size 29 (0x1d) .maxstack 8 @@ -16007,6 +16074,7 @@ .maxstack 8 IL_001b: nop IL_001c: ret } + get_Q { // Code size 7 (0x7) .maxstack 8 @@ -16014,6 +16082,7 @@ .maxstack 8 IL_0001: ldfld 0x04000005 IL_0006: ret } + set_Q { // Code size 8 (0x8) .maxstack 8 @@ -16022,6 +16091,7 @@ .maxstack 8 IL_0002: stfld 0x04000005 IL_0007: ret } + Deconstruct { // Code size 25 (0x19) .maxstack 8 @@ -16108,6 +16178,7 @@ public void Records_AddProperty_NonPrimary() }); g.VerifyIL(""" + get_Q { // Code size 7 (0x7) .maxstack 8 @@ -16115,6 +16186,7 @@ .maxstack 8 IL_0001: ldfld 0x04000004 IL_0006: ret } + set_Q { // Code size 8 (0x8) .maxstack 8 @@ -16351,7 +16423,8 @@ class C g.VerifyTypeRefNames("Object"); g.VerifyIL(""" - { + F + { // Code size 13 (0xd) .maxstack 8 IL_0000: ldstr 0x70000005 @@ -16359,6 +16432,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -16417,6 +16491,7 @@ void F2() {} g.VerifyTypeRefNames("Object"); g.VerifyIL(""" + F1 { // Code size 13 (0xd) .maxstack 8 @@ -16445,6 +16520,7 @@ class C g.VerifyTypeRefNames("Object"); g.VerifyIL(""" + F2 { // Code size 13 (0xd) .maxstack 8 @@ -16500,6 +16576,7 @@ void F2() {} g.VerifyTypeRefNames("Exception", "Object"); g.VerifyIL(""" + F1 { // Code size 13 (0xd) .maxstack 8 @@ -16508,6 +16585,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + .ctor { // Code size 10 (0xa) .maxstack 8 @@ -16538,6 +16616,7 @@ class C g.VerifyTypeRefNames("Object"); g.VerifyIL(""" + F2 { // Code size 13 (0xd) .maxstack 8 @@ -16594,6 +16673,84 @@ void F2() {} .Verify(); } + [Fact] + public void Method_Delete_PredefinedHotReloadException_DataSectionLiterals() + { + var parseOptions = TestOptions.Regular.WithFeature("experimental-data-section-string-literals", "0"); + + var exceptionSource = """ + namespace System.Runtime.CompilerServices + { + public class HotReloadException : Exception + { + public HotReloadException(string message, int code) : base(message) {} + } + } + """; + + using var _ = new EditAndContinueTest(targetFramework: TargetFramework.Net90, verification: Verification.FailsPEVerify, parseOptions: parseOptions) + .AddBaseline( + source: exceptionSource + """ + class C + { + void F1() {} + void F2() {} + } + """) + .AddGeneration( + // 1 + source: exceptionSource + """ + class C + { + void F2() {} + } + """, + edits: + [ + Edit(SemanticEditKind.Delete, symbolProvider: c => c.GetMember("C.F1"), newSymbolProvider: c => c.GetMember("C")), + ], + validator: g => + { + g.VerifySynthesizedMembers(); + g.VerifyTypeDefNames("#1", "__StaticArrayInitTypeSize=163", "A70F5C822D3106BF474269B4991AB592"); + g.VerifyTypeRefNames("Object", "CompilerGeneratedAttribute", "ValueType", "Encoding"); + + g.VerifyIL(""" + F1 + { + // Code size 13 (0xd) + .maxstack 8 + IL_0000: ldsfld 0x04000002 + IL_0005: ldc.i4.s -2 + IL_0007: newobj 0x06000004 + IL_000c: throw + } + BytesToString + { + // Code size 13 (0xd) + .maxstack 8 + IL_0000: call 0x0A000008 + IL_0005: ldarg.0 + IL_0006: ldarg.1 + IL_0007: callvirt 0x0A000009 + IL_000c: ret + } + .cctor + { + // Code size 21 (0x15) + .maxstack 8 + IL_0000: ldsflda 0x04000001 + IL_0005: ldc.i4 0xa3 + IL_000a: call 0x06000005 + IL_000f: stsfld 0x04000002 + IL_0014: ret + } + """); + }, + options: new EmitDifferenceOptions() { EmitFieldRva = true }) + .Verify(); + } + [Theory] [InlineData("void M1() { }")] [InlineData("void M1(string s) { }")] @@ -16665,7 +16822,8 @@ class N Handle(4, TableIndex.CustomAttribute) ]); - var expectedIL = """ + g.VerifyIL(""" + M1 { // Code size 13 (0xd) .maxstack 8 @@ -16674,6 +16832,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -16686,10 +16845,7 @@ .maxstack 8 IL_000a: stfld 0x04000001 IL_000f: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .Verify(); } @@ -16737,17 +16893,15 @@ void M2() { } Handle(3, TableIndex.MethodDef), }); - var expectedIL = """ + g.VerifyIL(""" + M2 { // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .AddGeneration( @@ -16784,7 +16938,8 @@ void M1() { } Handle(4, TableIndex.CustomAttribute) }); - var expectedIL = """ + g.VerifyIL(""" + M2 { // Code size 13 (0xd) .maxstack 8 @@ -16793,6 +16948,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -16805,10 +16961,7 @@ .maxstack 8 IL_000a: stfld 0x04000001 IL_000f: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .Verify(); } @@ -16863,7 +17016,8 @@ class C Handle(4, TableIndex.CustomAttribute) }); - var expectedIL = """ + g.VerifyIL(""" + M1 { // Code size 13 (0xd) .maxstack 8 @@ -16872,6 +17026,7 @@ .maxstack 8 IL_0007: newobj 0x06000003 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -16884,10 +17039,7 @@ .maxstack 8 IL_000a: stfld 0x04000001 IL_000f: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .AddGeneration( @@ -16914,6 +17066,7 @@ class C }); g.VerifyIL(""" + M1 { // Code size 9 (0x9) .maxstack 8 @@ -16992,8 +17145,9 @@ class C new CustomAttributeRow(Handle(5, TableIndex.TypeDef), Handle(6, TableIndex.MemberRef)) ]); - var expectedIL = """ - { + g.VerifyIL(""" + M1 + { // Code size 13 (0xd) .maxstack 8 IL_0000: ldstr 0x70000005 @@ -17001,6 +17155,7 @@ .maxstack 8 IL_0007: newobj 0x06000005 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -17013,10 +17168,7 @@ .maxstack 8 IL_000a: stfld 0x04000001 IL_000f: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .AddGeneration( @@ -17064,17 +17216,15 @@ void M1([B]int x) { } new CustomAttributeRow(Handle(3, TableIndex.MethodDef), Handle(2, TableIndex.MethodDef)) }); - var expectedIL = """ + g.VerifyIL(""" + M1 { // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .Verify(); } @@ -17128,7 +17278,8 @@ void Goo() { } Handle(1, TableIndex.StandAloneSig) }); - var expectedIL = """ + g.VerifyIL(""" + M1 { // Code size 7 (0x7) .maxstack 1 @@ -17139,10 +17290,7 @@ .maxstack 1 IL_0005: ldloc.0 IL_0006: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .AddGeneration( @@ -17181,7 +17329,8 @@ void Goo() { } Handle(4, TableIndex.CustomAttribute) }); - var expectedIL = """ + g.VerifyIL(""" + M1 { // Code size 13 (0xd) .maxstack 8 @@ -17190,6 +17339,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -17202,10 +17352,7 @@ .maxstack 8 IL_000a: stfld 0x04000001 IL_000f: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) @@ -17238,7 +17385,8 @@ void Goo() { } Handle(2, TableIndex.StandAloneSig) }); - var expectedIL = """ + g.VerifyIL(""" + M1 { // Code size 14 (0xe) .maxstack 1 @@ -17252,10 +17400,7 @@ .maxstack 1 IL_000c: ldloc.0 IL_000d: ret } - """; - - // Can't verify the IL of individual methods because that requires IMethodSymbolInternal implementations - g.VerifyIL(expectedIL); + """); }) .Verify(); } @@ -17324,6 +17469,7 @@ class C }); g.VerifyIL(""" + F { // Code size 13 (0xd) .maxstack 8 @@ -17332,6 +17478,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + b__0_0 { // Code size 12 (0xc) .maxstack 8 @@ -17340,6 +17487,7 @@ .maxstack 8 IL_0006: newobj 0x06000006 IL_000b: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -17398,6 +17546,7 @@ class C }); g.VerifyIL(""" + F { // Code size 30 (0x1e) .maxstack 8 @@ -17410,6 +17559,7 @@ .maxstack 8 IL_0018: stsfld 0x04000004 IL_001d: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -17418,6 +17568,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__0#2_0#2 { // Code size 8 (0x8) .maxstack 8 @@ -17467,6 +17618,7 @@ class C }); g.VerifyIL(""" + F { // Code size 13 (0xd) .maxstack 8 @@ -17475,6 +17627,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + b__0#2_0#2 { // Code size 12 (0xc) .maxstack 8 @@ -17576,7 +17729,8 @@ class C }); g.VerifyIL(""" - { + F + { // Code size 13 (0xd) .maxstack 8 IL_0000: ldstr 0x70000009 @@ -17584,6 +17738,7 @@ .maxstack 8 IL_0007: newobj 0x06000006 IL_000c: throw } + b__0#1_0#1 { // Code size 12 (0xc) .maxstack 8 @@ -17592,6 +17747,7 @@ .maxstack 8 IL_0006: newobj 0x06000006 IL_000b: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -17754,6 +17910,7 @@ class C }); g.VerifyIL(""" + F { // Code size 13 (0xd) .maxstack 8 @@ -17762,6 +17919,7 @@ .maxstack 8 IL_0007: newobj 0x0600000C IL_000c: throw } + b__0_0, b__0_1#1, b__0_2#2 { // Code size 12 (0xc) .maxstack 8 @@ -17770,6 +17928,7 @@ .maxstack 8 IL_0006: newobj 0x0600000C IL_000b: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -17816,6 +17975,7 @@ void F<[A]S>([A]T a, S b) where S : struct g.VerifyMemberRefNames(".ctor", "<>9__0#4_0#4", "<>9", "b__0#4_0#4", ".ctor", ".ctor", "<>9", ".ctor", "WriteLine"); g.VerifyIL(""" + F { // Code size 30 (0x1e) .maxstack 8 @@ -17828,6 +17988,7 @@ .maxstack 8 IL_0018: stsfld 0x0A000026 IL_001d: ret } + .cctor { // Code size 11 (0xb) .maxstack 8 @@ -17835,6 +17996,7 @@ .maxstack 8 IL_0005: stsfld 0x0A00002B IL_000a: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -17843,6 +18005,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + b__0#4_0#4 { // Code size 8 (0x8) .maxstack 8 @@ -17896,6 +18059,7 @@ class C }); g.VerifyIL(""" + F { // Code size 13 (0xd) .maxstack 8 @@ -17904,6 +18068,7 @@ .maxstack 8 IL_0007: newobj 0x0600000C IL_000c: throw } + b__0#4_0#4 { // Code size 12 (0xc) .maxstack 8 @@ -18029,6 +18194,7 @@ class C }); g.VerifyIL(""" + F { // Code size 13 (0xd) .maxstack 8 @@ -18037,6 +18203,7 @@ .maxstack 8 IL_0007: newobj 0x06000009 IL_000c: throw } + g__L|0_0, g__M|0_1#1 { // Code size 12 (0xc) .maxstack 8 @@ -18045,6 +18212,7 @@ .maxstack 8 IL_0006: newobj 0x06000009 IL_000b: throw } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -18096,6 +18264,7 @@ ref readonly T O(ref readonly T b) g.VerifyMemberRefNames(".ctor", ".ctor", "x", "g__O|0#3", ".ctor", "g__N|0#3_1#3"); g.VerifyIL(""" + F { // Code size 29 (0x1d) .maxstack 2 @@ -18113,12 +18282,14 @@ .maxstack 2 IL_001b: pop IL_001c: ret } + g__N|0#3_1#3 { // Code size 2 (0x2) .maxstack 8 IL_0000: ldarg.0 IL_0001: ret } + .ctor { // Code size 8 (0x8) .maxstack 8 @@ -18127,6 +18298,7 @@ .maxstack 8 IL_0006: nop IL_0007: ret } + g__O|0#3 { // Code size 9 (0x9) .maxstack 1 @@ -18139,6 +18311,7 @@ .maxstack 1 IL_0007: ldloc.0 IL_0008: ret } + b__2#3 { // Code size 12 (0xc) .maxstack 8 @@ -18187,6 +18360,7 @@ class C ]); g.VerifyIL(""" + F { // Code size 13 (0xd) .maxstack 8 @@ -18195,6 +18369,7 @@ .maxstack 8 IL_0007: newobj 0x06000009 IL_000c: throw } + g__N|0#3_1#3, g__O|0#3, b__2#3 { // Code size 12 (0xc) .maxstack 8 @@ -18334,6 +18509,7 @@ class C }); g.VerifyIL(""" + M { // Code size 13 (0xd) .maxstack 8 @@ -18342,6 +18518,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + M { // Code size 10 (0xa) .maxstack 8 @@ -18351,6 +18528,7 @@ .maxstack 8 IL_0008: pop IL_0009: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -18398,6 +18576,7 @@ class C }); g.VerifyIL(""" + M { // Code size 10 (0xa) .maxstack 8 @@ -18407,6 +18586,7 @@ .maxstack 8 IL_0008: pop IL_0009: ret } + M { // Code size 13 (0xd) .maxstack 8 @@ -18483,6 +18663,7 @@ class C }); g.VerifyIL(""" + M { // Code size 13 (0xd) .maxstack 8 @@ -18491,6 +18672,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + M { // Code size 7 (0x7) .maxstack 1 @@ -18501,6 +18683,7 @@ .maxstack 1 IL_0005: ldloc.0 IL_0006: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -18549,6 +18732,7 @@ class C }); g.VerifyIL(""" + M { // Code size 13 (0xd) .maxstack 1 @@ -18560,6 +18744,7 @@ .maxstack 1 IL_000b: ldloc.0 IL_000c: ret } + M { // Code size 13 (0xd) .maxstack 8 @@ -18637,6 +18822,7 @@ class C }); g.VerifyIL(""" + M { // Code size 13 (0xd) .maxstack 8 @@ -18645,6 +18831,7 @@ .maxstack 8 IL_0007: newobj 0x06000004 IL_000c: throw } + M { // Code size 10 (0xa) .maxstack 8 @@ -18654,6 +18841,7 @@ .maxstack 8 IL_0008: pop IL_0009: ret } + .ctor { // Code size 16 (0x10) .maxstack 8 @@ -18700,6 +18888,7 @@ class C }); g.VerifyIL(""" + M { // Code size 10 (0xa) .maxstack 8 @@ -18709,6 +18898,7 @@ .maxstack 8 IL_0008: pop IL_0009: ret } + M { // Code size 13 (0xd) .maxstack 8 @@ -19129,7 +19319,7 @@ .locals init (System.Span V_0, //x [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/69480")] - public void PrivateImplDetails_DataFields_Arrays() + public void PrivateImplDetails_DataFields_Arrays_FieldRvaNotSupported() { using var _ = new EditAndContinueTest() .AddBaseline( @@ -19233,7 +19423,95 @@ .maxstack 5 [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/69480")] - public void PrivateImplDetails_DataFields_StackAlloc() + public void PrivateImplDetails_DataFields_Arrays_FieldRvaSupported() + { + using var _ = new EditAndContinueTest() + .AddBaseline( + source: $$""" + class C + { + byte[] b = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + } + """, + validator: g => + { + g.VerifyTypeDefNames("", "C", "", "__StaticArrayInitTypeSize=10"); + g.VerifyFieldDefNames("b", "1F825AA2F0020EF7CF91DFA30DA4668D791C5D4824FC8E41354B89EC05795AB3"); + g.VerifyMethodDefNames(".ctor"); + }) + + .AddGeneration( + source: """ + class C + { + byte[] b = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + } + """, + edits: new[] + { + Edit(SemanticEditKind.Update, symbolProvider: c => c.GetParameterlessConstructor("C")), + }, + validator: g => + { + g.VerifyTypeDefNames("#1", "__StaticArrayInitTypeSize=11"); + g.VerifyFieldDefNames("78A6273103D17C39A0B6126E226CEC70E33337F4BC6A38067401B54A33E78EAD"); + g.VerifyMethodDefNames(".ctor"); + + g.VerifyEncLogDefinitions(new[] + { + Row(5, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(6, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddField), + Row(3, TableIndex.Field, EditAndContinueOperation.Default), + Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(2, TableIndex.ClassLayout, EditAndContinueOperation.Default), + Row(2, TableIndex.FieldRva, EditAndContinueOperation.Default), + Row(2, TableIndex.NestedClass, EditAndContinueOperation.Default) + }); + + g.VerifyEncMapDefinitions(new[] + { + Handle(5, TableIndex.TypeDef), + Handle(6, TableIndex.TypeDef), + Handle(3, TableIndex.Field), + Handle(1, TableIndex.MethodDef), + Handle(5, TableIndex.CustomAttribute), + Handle(2, TableIndex.ClassLayout), + Handle(2, TableIndex.FieldRva), + Handle(2, TableIndex.NestedClass) + }); + + g.VerifyIL("C..ctor", """ + { + // Code size 32 (0x20) + .maxstack 4 + IL_0000: ldarg.0 + IL_0001: ldc.i4.s 11 + IL_0003: newarr "byte" + IL_0008: dup + IL_0009: ldtoken "#1.__StaticArrayInitTypeSize=11 #1.78A6273103D17C39A0B6126E226CEC70E33337F4BC6A38067401B54A33E78EAD" + IL_000e: call "void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)" + IL_0013: stfld "byte[] C.b" + IL_0018: ldarg.0 + IL_0019: call "object..ctor()" + IL_001e: nop + IL_001f: ret + } + """); + + // trailing zeros for alignment: + g.VerifyEncFieldRvaData(""" + 78A6273103D17C39A0B6126E226CEC70E33337F4BC6A38067401B54A33E78EAD: 00-01-02-03-04-05-06-07-08-09-0A-00-00 + """); + }, + options: new EmitDifferenceOptions() { EmitFieldRva = true }) + .Verify(); + } + + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/69480")] + public void PrivateImplDetails_DataFields_StackAlloc_FieldRvaNotSupported() { using var _ = new EditAndContinueTest(targetFramework: TargetFramework.Net80, verification: Verification.Skipped) .AddBaseline( @@ -19342,20 +19620,20 @@ .locals init (System.ReadOnlySpan V_0, //b [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/69480")] - public void PrivateImplDetails_DataFields_Utf8() + public void PrivateImplDetails_DataFields_StackAlloc_FieldRvaSupported() { using var _ = new EditAndContinueTest(targetFramework: TargetFramework.Net80, verification: Verification.Skipped) .AddBaseline( - source: """ + source: $$""" class C { - System.ReadOnlySpan F() => "0123456789"u8; + void F() { System.ReadOnlySpan b = stackalloc byte[] { 0, 1, 2, 3, 4, 5, 6 }; } } """, validator: g => { - g.VerifyTypeDefNames("", "C", "", "__StaticArrayInitTypeSize=11"); - g.VerifyFieldDefNames("BEB0DBD1C6FAC1140DD817514F2FBDF501E246BF16C8E877E71187E9EB008189"); + g.VerifyTypeDefNames("", "C", "", "__StaticArrayInitTypeSize=7"); + g.VerifyFieldDefNames("57355AC3303C148F11AEF7CB179456B9232CDE33A818DFDA2C2FCB9325749A6B"); g.VerifyMethodDefNames("F", ".ctor"); }) @@ -19363,7 +19641,7 @@ class C source: """ class C { - System.ReadOnlySpan F() => "0123456789X"u8; + void F() { System.ReadOnlySpan b = stackalloc byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; } } """, edits: new[] @@ -19372,49 +19650,140 @@ class C }, validator: g => { - g.VerifyTypeDefNames(); - g.VerifyFieldDefNames(); + g.VerifyTypeDefNames("#1"); + g.VerifyFieldDefNames("8A851FF82EE7048AD09EC3847F1DDF44944104D2CBD17EF4E3DB22C6785A0D45"); g.VerifyMethodDefNames("F"); g.VerifyEncLogDefinitions(new[] { - Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default) + Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default), + Row(5, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddField), + Row(2, TableIndex.Field, EditAndContinueOperation.Default), + Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(2, TableIndex.FieldRva, EditAndContinueOperation.Default) }); g.VerifyEncMapDefinitions(new[] { - Handle(1, TableIndex.MethodDef) + Handle(5, TableIndex.TypeDef), + Handle(2, TableIndex.Field), + Handle(1, TableIndex.MethodDef), + Handle(5, TableIndex.CustomAttribute), + Handle(2, TableIndex.StandAloneSig), + Handle(2, TableIndex.FieldRva) }); g.VerifyIL("C.F", """ { - // Code size 73 (0x49) + // Code size 32 (0x20) .maxstack 4 - IL_0000: ldc.i4.s 12 - IL_0002: newarr "byte" - IL_0007: dup - IL_0008: ldc.i4.0 - IL_0009: ldc.i4.s 48 - IL_000b: stelem.i1 - IL_000c: dup - IL_000d: ldc.i4.1 - IL_000e: ldc.i4.s 49 - IL_0010: stelem.i1 - IL_0011: dup - IL_0012: ldc.i4.2 - IL_0013: ldc.i4.s 50 - IL_0015: stelem.i1 - IL_0016: dup - IL_0017: ldc.i4.3 - IL_0018: ldc.i4.s 51 - IL_001a: stelem.i1 - IL_001b: dup - IL_001c: ldc.i4.4 - IL_001d: ldc.i4.s 52 - IL_001f: stelem.i1 - IL_0020: dup - IL_0021: ldc.i4.5 - IL_0022: ldc.i4.s 53 + .locals init (System.ReadOnlySpan V_0, //b + System.Span V_1) + IL_0000: nop + IL_0001: ldc.i4.8 + IL_0002: conv.u + IL_0003: localloc + IL_0005: dup + IL_0006: ldsflda "long #1.8A851FF82EE7048AD09EC3847F1DDF44944104D2CBD17EF4E3DB22C6785A0D45" + IL_000b: ldc.i4.8 + IL_000c: unaligned. 1 + IL_000f: cpblk + IL_0011: ldc.i4.8 + IL_0012: newobj "System.Span..ctor(void*, int)" + IL_0017: stloc.1 + IL_0018: ldloc.1 + IL_0019: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" + IL_001e: stloc.0 + IL_001f: ret + } + """); + + // trailing zeros for alignment: + g.VerifyEncFieldRvaData(""" + 8A851FF82EE7048AD09EC3847F1DDF44944104D2CBD17EF4E3DB22C6785A0D45: 00-01-02-03-04-05-06-07 + """); + }, + options: new EmitDifferenceOptions() { EmitFieldRva = true }) + .Verify(); + } + + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/69480")] + public void PrivateImplDetails_DataFields_Utf8_FieldRvaNotSupported() + { + using var _ = new EditAndContinueTest(targetFramework: TargetFramework.Net80, verification: Verification.Skipped) + .AddBaseline( + source: """ + class C + { + System.ReadOnlySpan F() => "0123456789"u8; + } + """, + validator: g => + { + g.VerifyTypeDefNames("", "C", "", "__StaticArrayInitTypeSize=11"); + g.VerifyFieldDefNames("BEB0DBD1C6FAC1140DD817514F2FBDF501E246BF16C8E877E71187E9EB008189"); + g.VerifyMethodDefNames("F", ".ctor"); + }) + + .AddGeneration( + source: """ + class C + { + System.ReadOnlySpan F() => "0123456789X"u8; + } + """, + edits: new[] + { + Edit(SemanticEditKind.Update, symbolProvider: c => c.GetMember("C.F")), + }, + validator: g => + { + g.VerifyTypeDefNames(); + g.VerifyFieldDefNames(); + g.VerifyMethodDefNames("F"); + + g.VerifyEncLogDefinitions(new[] + { + Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default) + }); + + g.VerifyEncMapDefinitions(new[] + { + Handle(1, TableIndex.MethodDef) + }); + + g.VerifyIL("C.F", """ + { + // Code size 73 (0x49) + .maxstack 4 + IL_0000: ldc.i4.s 12 + IL_0002: newarr "byte" + IL_0007: dup + IL_0008: ldc.i4.0 + IL_0009: ldc.i4.s 48 + IL_000b: stelem.i1 + IL_000c: dup + IL_000d: ldc.i4.1 + IL_000e: ldc.i4.s 49 + IL_0010: stelem.i1 + IL_0011: dup + IL_0012: ldc.i4.2 + IL_0013: ldc.i4.s 50 + IL_0015: stelem.i1 + IL_0016: dup + IL_0017: ldc.i4.3 + IL_0018: ldc.i4.s 51 + IL_001a: stelem.i1 + IL_001b: dup + IL_001c: ldc.i4.4 + IL_001d: ldc.i4.s 52 + IL_001f: stelem.i1 + IL_0020: dup + IL_0021: ldc.i4.5 + IL_0022: ldc.i4.s 53 IL_0024: stelem.i1 IL_0025: dup IL_0026: ldc.i4.6 @@ -19446,6 +19815,493 @@ .maxstack 4 .Verify(); } + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/69480")] + public void PrivateImplDetails_DataFields_Utf8_FieldRvaSupported() + { + using var _ = new EditAndContinueTest(targetFramework: TargetFramework.Net80, verification: Verification.Skipped) + .AddBaseline( + source: """ + class C + { + System.ReadOnlySpan F() => "0123456789"u8; + } + """, + validator: g => + { + g.VerifyTypeDefNames("", "C", "", "__StaticArrayInitTypeSize=11"); + g.VerifyFieldDefNames("BEB0DBD1C6FAC1140DD817514F2FBDF501E246BF16C8E877E71187E9EB008189"); + g.VerifyMethodDefNames("F", ".ctor"); + }) + + .AddGeneration( + source: """ + class C + { + System.ReadOnlySpan F() => "0123456789X"u8; + } + """, + edits: new[] + { + Edit(SemanticEditKind.Update, symbolProvider: c => c.GetMember("C.F")), + }, + validator: g => + { + g.VerifyTypeDefNames("#1", "__StaticArrayInitTypeSize=12"); + g.VerifyFieldDefNames("AFB1C33C5229BFF7EF739BA44DA795A2B68A49E06001C07C5B026CAA6C6322BB"); + g.VerifyMethodDefNames("F"); + + g.VerifyEncLogDefinitions(new[] + { + Row(5, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(6, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddField), + Row(2, TableIndex.Field, EditAndContinueOperation.Default), + Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(2, TableIndex.ClassLayout, EditAndContinueOperation.Default), + Row(2, TableIndex.FieldRva, EditAndContinueOperation.Default), + Row(2, TableIndex.NestedClass, EditAndContinueOperation.Default) + }); + + g.VerifyEncMapDefinitions(new[] + { + Handle(5, TableIndex.TypeDef), + Handle(6, TableIndex.TypeDef), + Handle(2, TableIndex.Field), + Handle(1, TableIndex.MethodDef), + Handle(5, TableIndex.CustomAttribute), + Handle(2, TableIndex.ClassLayout), + Handle(2, TableIndex.FieldRva), + Handle(2, TableIndex.NestedClass) + }); + + g.VerifyIL("C.F", """ + { + // Code size 13 (0xd) + .maxstack 2 + IL_0000: ldsflda "#1.__StaticArrayInitTypeSize=12 #1.AFB1C33C5229BFF7EF739BA44DA795A2B68A49E06001C07C5B026CAA6C6322BB" + IL_0005: ldc.i4.s 11 + IL_0007: newobj "System.ReadOnlySpan..ctor(void*, int)" + IL_000c: ret + } + """); + + // trailing zeros for alignment: + g.VerifyEncFieldRvaData($""" + AFB1C33C5229BFF7EF739BA44DA795A2B68A49E06001C07C5B026CAA6C6322BB: {BitConverter.ToString(Encoding.UTF8.GetBytes("0123456789X"))}-00-00-00-00-00-00-00 + """); + }, + options: new EmitDifferenceOptions() { EmitFieldRva = true }) + .Verify(); + } + + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/69480")] + public void PrivateImplDetails_DataSectionStringLiterals_FieldRvaSupported() + { + var parseOptions = TestOptions.Regular.WithFeature("experimental-data-section-string-literals", "0"); + + using var _ = new EditAndContinueTest(targetFramework: TargetFramework.Net90, verification: Verification.Skipped, parseOptions: parseOptions) + .AddBaseline( + source: """ + class C + { + string F() => "0123456789"; + } + """, + validator: g => + { + g.VerifyTypeDefNames("", "C", "", "__StaticArrayInitTypeSize=10", "E353667619EC664B49655FC9692165FB"); + g.VerifyFieldDefNames("84D89877F0D4041EFB6BF91A16F0248F2FD573E6AF05C19F96BEDB9F882F7882", "s"); + g.VerifyMethodDefNames("F", ".ctor", "BytesToString", ".cctor"); + }) + .AddGeneration( + source: """ + class C + { + string F() => "0123456789X"; + } + """, + edits: + [ + Edit(SemanticEditKind.Update, symbolProvider: c => c.GetMember("C.F")), + ], + validator: g => + { + g.VerifyTypeDefNames("#1", "__StaticArrayInitTypeSize=11", "6D2201523542AEFFB91657B2AEBDC84B"); + g.VerifyFieldDefNames("ACE59E7D984CCEB2D860A056A3386344236CE5C42C978E26ECE3F35956DAC3AD", "s"); + g.VerifyMethodDefNames("F", "BytesToString", ".cctor"); + + g.VerifyEncLogDefinitions( + [ + Row(6, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(7, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(8, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(6, TableIndex.TypeDef, EditAndContinueOperation.AddField), + Row(3, TableIndex.Field, EditAndContinueOperation.Default), + Row(8, TableIndex.TypeDef, EditAndContinueOperation.AddField), + Row(4, TableIndex.Field, EditAndContinueOperation.Default), + Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(6, TableIndex.TypeDef, EditAndContinueOperation.AddMethod), + Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(8, TableIndex.TypeDef, EditAndContinueOperation.AddMethod), + Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(5, TableIndex.MethodDef, EditAndContinueOperation.AddParameter), + Row(3, TableIndex.Param, EditAndContinueOperation.Default), + Row(5, TableIndex.MethodDef, EditAndContinueOperation.AddParameter), + Row(4, TableIndex.Param, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(2, TableIndex.ClassLayout, EditAndContinueOperation.Default), + Row(2, TableIndex.FieldRva, EditAndContinueOperation.Default), + Row(3, TableIndex.NestedClass, EditAndContinueOperation.Default), + Row(4, TableIndex.NestedClass, EditAndContinueOperation.Default) + ]); + + g.VerifyEncMapDefinitions( + [ + Handle(6, TableIndex.TypeDef), + Handle(7, TableIndex.TypeDef), + Handle(8, TableIndex.TypeDef), + Handle(3, TableIndex.Field), + Handle(4, TableIndex.Field), + Handle(1, TableIndex.MethodDef), + Handle(5, TableIndex.MethodDef), + Handle(6, TableIndex.MethodDef), + Handle(3, TableIndex.Param), + Handle(4, TableIndex.Param), + Handle(6, TableIndex.CustomAttribute), + Handle(2, TableIndex.ClassLayout), + Handle(2, TableIndex.FieldRva), + Handle(3, TableIndex.NestedClass), + Handle(4, TableIndex.NestedClass) + ]); + + g.VerifyIL("C.F", """ + { + // Code size 6 (0x6) + .maxstack 1 + IL_0000: ldsfld "string #1.6D2201523542AEFFB91657B2AEBDC84B.s" + IL_0005: ret + } + """); + + // trailing zeros for alignment: + g.VerifyEncFieldRvaData($""" + ACE59E7D984CCEB2D860A056A3386344236CE5C42C978E26ECE3F35956DAC3AD: {BitConverter.ToString(Encoding.UTF8.GetBytes("0123456789X"))}-00 + """); + }, + options: new EmitDifferenceOptions() { EmitFieldRva = true }) + .Verify(); + } + + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/69480")] + public void PrivateImplDetails_DataSectionStringLiterals_FieldRvaNotSupported() + { + var parseOptions = TestOptions.Regular.WithFeature("experimental-data-section-string-literals", "0"); + + using var _ = new EditAndContinueTest(targetFramework: TargetFramework.Net90, verification: Verification.Skipped, parseOptions: parseOptions) + .AddBaseline( + source: """ + class C + { + string F() => "0123456789"; + } + """, + validator: g => + { + g.VerifyTypeDefNames("", "C", "", "__StaticArrayInitTypeSize=10", "E353667619EC664B49655FC9692165FB"); + g.VerifyFieldDefNames("84D89877F0D4041EFB6BF91A16F0248F2FD573E6AF05C19F96BEDB9F882F7882", "s"); + g.VerifyMethodDefNames("F", ".ctor", "BytesToString", ".cctor"); + }) + .AddGeneration( + source: """ + class C + { + string F() => "0123456789X"; + } + """, + edits: + [ + Edit(SemanticEditKind.Update, symbolProvider: c => c.GetMember("C.F")), + ], + validator: g => + { + g.VerifyTypeDefNames(); + g.VerifyFieldDefNames(); + g.VerifyMethodDefNames("F"); + + g.VerifyEncLogDefinitions( + [ + Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default) + ]); + + g.VerifyEncMapDefinitions( + [ + Handle(1, TableIndex.MethodDef) + ]); + + g.VerifyIL("C.F", """ + { + // Code size 6 (0x6) + .maxstack 1 + IL_0000: ldstr "0123456789X" + IL_0005: ret + } + """); + }) + .Verify(); + } + + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/69480")] + public void PrivateImplDetails_DataSectionStringLiterals_HeapOverflow_FieldRvaSupported() + { + // The longest string that can fit in the #US heap. The next string would overflow the heap. + var baseString = new string('x', (1 << 23) - 3); + + using var _ = new EditAndContinueTest(targetFramework: TargetFramework.Net90, verification: Verification.Skipped) + .AddBaseline( + source: $$""" + class C + { + string F() => "{{baseString}}"; + } + """, + validator: g => + { + g.VerifyTypeDefNames("", "C"); + g.VerifyFieldDefNames(); + g.VerifyMethodDefNames("F", ".ctor"); + }) + .AddGeneration( + source: """ + class C + { + string F() => "0123456789"; + } + """, + edits: + [ + Edit(SemanticEditKind.Update, symbolProvider: c => c.GetMember("C.F")), + ], + validator: g => + { + g.VerifyTypeDefNames("#1", "__StaticArrayInitTypeSize=10", "E353667619EC664B49655FC9692165FB"); + g.VerifyFieldDefNames("84D89877F0D4041EFB6BF91A16F0248F2FD573E6AF05C19F96BEDB9F882F7882", "s"); + g.VerifyMethodDefNames("F", "BytesToString", ".cctor"); + + g.VerifyEncLogDefinitions( + [ + Row(3, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(4, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(5, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddField), + Row(1, TableIndex.Field, EditAndContinueOperation.Default), + Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddField), + Row(2, TableIndex.Field, EditAndContinueOperation.Default), + Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddMethod), + Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod), + Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(3, TableIndex.MethodDef, EditAndContinueOperation.AddParameter), + Row(1, TableIndex.Param, EditAndContinueOperation.Default), + Row(3, TableIndex.MethodDef, EditAndContinueOperation.AddParameter), + Row(2, TableIndex.Param, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(1, TableIndex.ClassLayout, EditAndContinueOperation.Default), + Row(1, TableIndex.FieldRva, EditAndContinueOperation.Default), + Row(1, TableIndex.NestedClass, EditAndContinueOperation.Default), + Row(2, TableIndex.NestedClass, EditAndContinueOperation.Default) + ]); + + g.VerifyEncMapDefinitions( + [ + Handle(3, TableIndex.TypeDef), + Handle(4, TableIndex.TypeDef), + Handle(5, TableIndex.TypeDef), + Handle(1, TableIndex.Field), + Handle(2, TableIndex.Field), + Handle(1, TableIndex.MethodDef), + Handle(3, TableIndex.MethodDef), + Handle(4, TableIndex.MethodDef), + Handle(1, TableIndex.Param), + Handle(2, TableIndex.Param), + Handle(4, TableIndex.CustomAttribute), + Handle(1, TableIndex.ClassLayout), + Handle(1, TableIndex.FieldRva), + Handle(1, TableIndex.NestedClass), + Handle(2, TableIndex.NestedClass) + ]); + + g.VerifyIL("C.F", """ + { + // Code size 6 (0x6) + .maxstack 1 + IL_0000: ldsfld "string #1.E353667619EC664B49655FC9692165FB.s" + IL_0005: ret + } + """); + + // trailing zeros for alignment: + g.VerifyEncFieldRvaData($""" + 84D89877F0D4041EFB6BF91A16F0248F2FD573E6AF05C19F96BEDB9F882F7882: {BitConverter.ToString(Encoding.UTF8.GetBytes("0123456789"))}-00-00 + """); + }, + options: new EmitDifferenceOptions() { EmitFieldRva = true }) + .Verify(); + } + + [Fact] + public void PrivateImplDetails_DataSectionStringLiterals_StringReuse_FieldRvaSupported() + { + // Literals are currently only reused within generation. + + var baseString = new string('x', (1 << 23) - 100); + var newString1 = new string('1', 40); + var newString2 = new string('2', 80); + + using var _ = new EditAndContinueTest(targetFramework: TargetFramework.Net90, verification: Verification.Skipped) + .AddBaseline( + source: $$""" + class C + { + void G(string a, string b, string c) {} + + void F() => G("{{baseString}}", "{{newString1}}", ""); + } + """, + validator: g => + { + g.VerifyTypeDefNames("", "C"); + g.VerifyFieldDefNames(); + g.VerifyMethodDefNames("G", "F", ".ctor"); + }) + .AddGeneration( + source: $$""" + class C + { + void G(string a, string b, string c) {} + + void F() => G("{{newString2}}", "{{newString2}}", "{{newString1}}"); + } + """, + edits: + [ + Edit(SemanticEditKind.Update, symbolProvider: c => c.GetMember("C.F")), + ], + validator: g => + { + g.VerifyTypeDefNames("#1", "__StaticArrayInitTypeSize=40", "62CF64E173E5BF9EF5312BB6D57CC26C"); + g.VerifyFieldDefNames("468D019EA81224AECA7EE270B11959D8A187F6F0B6A3FEBFF1C34DC1D66C8D85", "s"); + g.VerifyMethodDefNames("F", "BytesToString", ".cctor"); + + g.VerifyEncLogDefinitions( + [ + Row(3, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(4, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(5, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddField), + Row(1, TableIndex.Field, EditAndContinueOperation.Default), + Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddField), + Row(2, TableIndex.Field, EditAndContinueOperation.Default), + Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddMethod), + Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod), + Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.MethodDef, EditAndContinueOperation.AddParameter), + Row(4, TableIndex.Param, EditAndContinueOperation.Default), + Row(4, TableIndex.MethodDef, EditAndContinueOperation.AddParameter), + Row(5, TableIndex.Param, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(1, TableIndex.ClassLayout, EditAndContinueOperation.Default), + Row(1, TableIndex.FieldRva, EditAndContinueOperation.Default), + Row(1, TableIndex.NestedClass, EditAndContinueOperation.Default), + Row(2, TableIndex.NestedClass, EditAndContinueOperation.Default) + ]); + + g.VerifyEncMapDefinitions( + [ + Handle(3, TableIndex.TypeDef), + Handle(4, TableIndex.TypeDef), + Handle(5, TableIndex.TypeDef), + Handle(1, TableIndex.Field), + Handle(2, TableIndex.Field), + Handle(2, TableIndex.MethodDef), + Handle(4, TableIndex.MethodDef), + Handle(5, TableIndex.MethodDef), + Handle(4, TableIndex.Param), + Handle(5, TableIndex.Param), + Handle(4, TableIndex.CustomAttribute), + Handle(1, TableIndex.ClassLayout), + Handle(1, TableIndex.FieldRva), + Handle(1, TableIndex.NestedClass), + Handle(2, TableIndex.NestedClass) + ]); + + g.VerifyIL("C.F", """ + { + // Code size 23 (0x17) + .maxstack 4 + IL_0000: ldarg.0 + IL_0001: ldstr "22222222222222222222222222222222222222222222222222222222222222222222222222222222" + IL_0006: ldstr "22222222222222222222222222222222222222222222222222222222222222222222222222222222" + IL_000b: ldsfld "string #1.62CF64E173E5BF9EF5312BB6D57CC26C.s" + IL_0010: call "void C.G(string, string, string)" + IL_0015: nop + IL_0016: ret + } + """); + }, + options: new EmitDifferenceOptions() { EmitFieldRva = true }) + .Verify(); + } + + [Fact] + public void PrivateImplDetails_DataSectionStringLiterals_HeapOverflow_FieldRvaNotSupported() + { + // The max number of bytes that can fit into #US the heap is 2^29 - 1, + // but each string also needs to have an offset < 0x1000000 (2^24) to be addressable by a token. + // If the string is larger than that the next string can't be emitted. + var baseString = new string('x', 1 << 23); + + using var _ = new EditAndContinueTest(targetFramework: TargetFramework.Net90, verification: Verification.Skipped) + .AddBaseline( + source: $$""" + class C + { + string F() => "{{baseString}}"; + } + """, + validator: g => + { + g.VerifyTypeDefNames("", "C"); + g.VerifyFieldDefNames(); + g.VerifyMethodDefNames("F", ".ctor"); + }) + .AddGeneration( + source: """ + class C + { + string F() => "new string that doesn't fit"; + } + """, + edits: + [ + Edit(SemanticEditKind.Update, symbolProvider: c => c.GetMember("C.F")), + ], + expectedErrors: + [ + // (3,19): error CS9307: Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application. + // string F() => "new string that doesn't fit"; + Diagnostic(ErrorCode.ERR_TooManyUserStrings_RestartRequired, @"""new string that doesn't fit""").WithLocation(3, 19) + ]) + .Verify(); + } + [Theory] [InlineData("ComputeStringHash", "string")] [InlineData("ComputeSpanHash", "Span")] diff --git a/src/Compilers/Core/CodeAnalysisTest/MetadataReferences/MetadataHelpersTests.cs b/src/Compilers/Core/CodeAnalysisTest/MetadataReferences/MetadataHelpersTests.cs index 63341865aa107..b6494e4c279da 100644 --- a/src/Compilers/Core/CodeAnalysisTest/MetadataReferences/MetadataHelpersTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/MetadataReferences/MetadataHelpersTests.cs @@ -503,5 +503,16 @@ public void ObfuscatedNamespaceNames_02() Assert.Equal("a", nestedNamespaces.ElementAt(0).Key); Assert.Equal("b", nestedNamespaces.ElementAt(1).Key); } + + [Theory] + [InlineData("")] + [InlineData("abc")] + [InlineData("\u1234")] + public static void GetUserStringBlobSize(string str) + { + var builder = new BlobBuilder(); + builder.WriteUserString(str); + Assert.Equal(builder.Count, MetadataHelpers.GetUserStringBlobSize(str)); + } } } diff --git a/src/Compilers/Core/Portable/CodeGen/ILBuilder.cs b/src/Compilers/Core/Portable/CodeGen/ILBuilder.cs index 2a170dbc2ffa9..3d7af82151476 100644 --- a/src/Compilers/Core/Portable/CodeGen/ILBuilder.cs +++ b/src/Compilers/Core/Portable/CodeGen/ILBuilder.cs @@ -2,15 +2,15 @@ // 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; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Reflection.Metadata; using Microsoft.CodeAnalysis.Debugging; +using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; @@ -20,20 +20,21 @@ namespace Microsoft.CodeAnalysis.CodeGen internal sealed partial class ILBuilder { private readonly OptimizationLevel _optimizations; - internal readonly LocalSlotManager LocalSlotManager; + internal readonly LocalSlotManager? LocalSlotManager; + private readonly DiagnosticBag _diagnostics; private readonly LocalScopeManager _scopeManager; // internal for testing - internal readonly ITokenDeferral module; + internal readonly CommonPEModuleBuilder module; //leader block is the entry point of the method body internal readonly BasicBlock leaderBlock; private EmitState _emitState; - private BasicBlock _lastCompleteBlock; - private BasicBlock _currentBlock; + private BasicBlock? _lastCompleteBlock; + private BasicBlock? _currentBlock; - private SyntaxTree _lastSeqPointTree; + private SyntaxTree? _lastSeqPointTree; private readonly SmallDictionary _labelInfos; private readonly bool _areLocalsZeroed; @@ -42,11 +43,11 @@ internal sealed partial class ILBuilder // This data is only relevant when builder has been realized. internal ImmutableArray RealizedIL; internal ImmutableArray RealizedExceptionHandlers; - internal SequencePointList RealizedSequencePoints; + internal SequencePointList? RealizedSequencePoints; // debug sequence points from all blocks, note that each // sequence point references absolute IL offset via IL marker - public ArrayBuilder SeqPointsOpt; + public ArrayBuilder? SeqPointsOpt; /// /// In some cases we have to get a final IL offset during emit phase, for example for @@ -60,17 +61,19 @@ internal sealed partial class ILBuilder /// will be put into array. Note that only markers from reachable blocks /// are materialized, the rest will have offset -1. /// - private ArrayBuilder _allocatedILMarkers; + private ArrayBuilder? _allocatedILMarkers; // Since blocks are created lazily in GetCurrentBlock, // pendingBlockCreate is set to true when a block must be // created, in particular for leader blocks in exception handlers. private bool _pendingBlockCreate; - internal ILBuilder(ITokenDeferral module, LocalSlotManager localSlotManager, OptimizationLevel optimizations, bool areLocalsZeroed) + internal ILBuilder(CommonPEModuleBuilder module, LocalSlotManager? localSlotManager, DiagnosticBag diagnostics, OptimizationLevel optimizations, bool areLocalsZeroed) { this.module = module; this.LocalSlotManager = localSlotManager; + + _diagnostics = diagnostics; _emitState = default(EmitState); _scopeManager = new LocalScopeManager(); @@ -95,6 +98,7 @@ private BasicBlock GetCurrentBlock() return _currentBlock; } + [MemberNotNull(nameof(_currentBlock))] private void CreateBlock() { Debug.Assert(_currentBlock == null); @@ -103,6 +107,7 @@ private void CreateBlock() UpdatesForCreatedBlock(block); } + [MemberNotNull(nameof(_currentBlock))] private SwitchBlock CreateSwitchBlock() { // end the current block @@ -113,10 +118,13 @@ private SwitchBlock CreateSwitchBlock() return switchBlock; } + [MemberNotNull(nameof(_currentBlock))] private void UpdatesForCreatedBlock(BasicBlock block) { - _currentBlock = block; + Debug.Assert(_lastCompleteBlock != null); Debug.Assert(_lastCompleteBlock.NextBlock == null); + + _currentBlock = block; _lastCompleteBlock.NextBlock = block; _pendingBlockCreate = false; ReconcileTrailingMarkers(); @@ -153,29 +161,33 @@ private void ReconcileTrailingMarkers() // should be moved to the next block if (_lastCompleteBlock != null && _lastCompleteBlock.BranchCode == ILOpCode.Nop && - _lastCompleteBlock.LastILMarker >= 0 && - _allocatedILMarkers[_lastCompleteBlock.LastILMarker].BlockOffset == _lastCompleteBlock.RegularInstructionsLength) + _lastCompleteBlock.LastILMarker >= 0) { - int startMarker = -1; - int endMarker = -1; + Debug.Assert(_allocatedILMarkers != null); - while (_lastCompleteBlock.LastILMarker >= 0 && - _allocatedILMarkers[_lastCompleteBlock.LastILMarker].BlockOffset == _lastCompleteBlock.RegularInstructionsLength) + if (_allocatedILMarkers[_lastCompleteBlock.LastILMarker].BlockOffset == _lastCompleteBlock.RegularInstructionsLength) { - Debug.Assert((startMarker < 0) || (startMarker == (_lastCompleteBlock.LastILMarker + 1))); - startMarker = _lastCompleteBlock.LastILMarker; - if (endMarker < 0) + int startMarker = -1; + int endMarker = -1; + + while (_lastCompleteBlock.LastILMarker >= 0 && + _allocatedILMarkers[_lastCompleteBlock.LastILMarker].BlockOffset == _lastCompleteBlock.RegularInstructionsLength) { - endMarker = _lastCompleteBlock.LastILMarker; + Debug.Assert((startMarker < 0) || (startMarker == (_lastCompleteBlock.LastILMarker + 1))); + startMarker = _lastCompleteBlock.LastILMarker; + if (endMarker < 0) + { + endMarker = _lastCompleteBlock.LastILMarker; + } + _lastCompleteBlock.RemoveTailILMarker(_lastCompleteBlock.LastILMarker); } - _lastCompleteBlock.RemoveTailILMarker(_lastCompleteBlock.LastILMarker); - } - BasicBlock current = this.GetCurrentBlock(); - for (int marker = startMarker; marker <= endMarker; marker++) - { - current.AddILMarker(marker); - _allocatedILMarkers[marker] = new ILMarker() { BlockOffset = (int)current.RegularInstructionsLength, AbsoluteOffset = -1 }; + BasicBlock current = this.GetCurrentBlock(); + for (int marker = startMarker; marker <= endMarker; marker++) + { + current.AddILMarker(marker); + _allocatedILMarkers[marker] = new ILMarker() { BlockOffset = (int)current.RegularInstructionsLength, AbsoluteOffset = -1 }; + } } } } @@ -369,7 +381,7 @@ private static void RedirectBranchToBlockedDestination(BasicBlock block, object // if branch is blocked by a nonterminating finally, // returns label for a landing block used as a target of blocked branches // Otherwise returns null - private static object BlockedBranchDestination(BasicBlock src, BasicBlock dest) + private static object? BlockedBranchDestination(BasicBlock src, BasicBlock dest) { var srcHandler = src.EnclosingHandler; @@ -382,9 +394,9 @@ private static object BlockedBranchDestination(BasicBlock src, BasicBlock dest) return BlockedBranchDestinationSlow(dest.EnclosingHandler, srcHandler); } - private static object BlockedBranchDestinationSlow(ExceptionHandlerScope destHandler, ExceptionHandlerScope srcHandler) + private static object? BlockedBranchDestinationSlow(ExceptionHandlerScope destHandler, ExceptionHandlerScope srcHandler) { - ScopeInfo destHandlerScope = null; + ScopeInfo? destHandlerScope = null; if (destHandler != null) { destHandlerScope = destHandler.ContainingExceptionScope; @@ -516,11 +528,11 @@ private bool ForwardLabelsNoLeaving() var labelInfo = _labelInfos[label]; var targetBlock = labelInfo.bb; - Debug.Assert(!IsSpecialEndHandlerBlock(targetBlock)); + Debug.Assert(targetBlock != null && !IsSpecialEndHandlerBlock(targetBlock)); if (targetBlock.HasNoRegularInstructions) { - BasicBlock targetsTarget = null; + BasicBlock? targetsTarget = null; switch (targetBlock.BranchCode) { case ILOpCode.Br: @@ -576,11 +588,11 @@ private bool ForwardLabelsAllowLeaving() var targetBlock = labelInfo.bb; - Debug.Assert(!IsSpecialEndHandlerBlock(targetBlock)); + Debug.Assert(targetBlock != null && !IsSpecialEndHandlerBlock(targetBlock)); if (targetBlock.HasNoRegularInstructions) { - BasicBlock targetsTarget = null; + BasicBlock? targetsTarget = null; switch (targetBlock.BranchCode) { case ILOpCode.Br: @@ -898,6 +910,8 @@ private void RealizeBlocks() Debug.Assert(blockLastMarker >= blockFirstMarker); for (int i = blockFirstMarker; i <= blockLastMarker; i++) { + Debug.Assert(_allocatedILMarkers != null); + int blockOffset = _allocatedILMarkers[i].BlockOffset; int absoluteOffset = writer.Count + blockOffset; _allocatedILMarkers[i] = new ILMarker() { BlockOffset = blockOffset, AbsoluteOffset = absoluteOffset }; @@ -1099,7 +1113,7 @@ internal bool IsJustPastLabel() return _emitState.InstructionsEmitted == _instructionCountAtLastLabel; } - internal void OpenLocalScope(ScopeType scopeType = ScopeType.Variable, Cci.ITypeReference exceptionType = null) + internal void OpenLocalScope(ScopeType scopeType = ScopeType.Variable, Cci.ITypeReference? exceptionType = null) { if (scopeType == ScopeType.TryCatchFinally && IsJustPastLabel()) { @@ -1267,7 +1281,7 @@ private string GetDebuggerDisplay() if (visType != null) { var method = visType.GetTypeInfo().GetDeclaredMethod("ILBuilderToString"); - return (string)method.Invoke(null, new object[] { this, null, null }); + return (string)method!.Invoke(null, [this, null, null])!; } #endif diff --git a/src/Compilers/Core/Portable/CodeGen/ILBuilderEmit.cs b/src/Compilers/Core/Portable/CodeGen/ILBuilderEmit.cs index 03b1f616d8dda..80e5bb29a3e59 100644 --- a/src/Compilers/Core/Portable/CodeGen/ILBuilderEmit.cs +++ b/src/Compilers/Core/Portable/CodeGen/ILBuilderEmit.cs @@ -7,8 +7,6 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Reflection.Metadata; -using Roslyn.Utilities; -using static System.Linq.ImmutableArrayExtensions; namespace Microsoft.CodeAnalysis.CodeGen { @@ -40,15 +38,9 @@ internal void EmitOpCode(ILOpCode code, int stackAdjustment) _emitState.InstructionAdded(); } - internal void EmitToken(string value) + internal void EmitToken(Cci.IReference value, SyntaxNode? syntaxNode, Cci.MetadataWriter.RawTokenEncoding encoding = 0) { - uint token = module?.GetFakeStringTokenForIL(value) ?? 0xFFFF; - this.GetCurrentWriter().WriteUInt32(token); - } - - internal void EmitToken(Cci.IReference value, SyntaxNode? syntaxNode, DiagnosticBag diagnostics, Cci.MetadataWriter.RawTokenEncoding encoding = 0) - { - uint token = module?.GetFakeSymbolTokenForIL(value, syntaxNode, diagnostics) ?? 0xFFFF; + uint token = module.GetFakeSymbolTokenForIL(value, syntaxNode, _diagnostics); if (encoding != Cci.MetadataWriter.RawTokenEncoding.None) { token = Cci.MetadataWriter.GetRawToken(encoding, token); @@ -56,9 +48,9 @@ internal void EmitToken(Cci.IReference value, SyntaxNode? syntaxNode, Diagnostic this.GetCurrentWriter().WriteUInt32(token); } - internal void EmitToken(Cci.ISignature value, SyntaxNode? syntaxNode, DiagnosticBag diagnostics) + internal void EmitToken(Cci.ISignature value, SyntaxNode? syntaxNode) { - uint token = module?.GetFakeSymbolTokenForIL(value, syntaxNode, diagnostics) ?? 0xFFFF; + uint token = module.GetFakeSymbolTokenForIL(value, syntaxNode, _diagnostics); this.GetCurrentWriter().WriteUInt32(token); } @@ -76,11 +68,11 @@ internal void EmitModuleVersionIdStringToken() internal void EmitSourceDocumentIndexToken(Cci.DebugSourceDocument document) { - var token = Cci.MetadataWriter.GetRawToken(Cci.MetadataWriter.RawTokenEncoding.DocumentRowId, module?.GetSourceDocumentIndexForIL(document) ?? 0xFFFF); + var token = Cci.MetadataWriter.GetRawToken(Cci.MetadataWriter.RawTokenEncoding.DocumentRowId, module.GetSourceDocumentIndexForIL(document)); this.GetCurrentWriter().WriteUInt32(token); } - internal void EmitArrayBlockInitializer(ImmutableArray data, SyntaxNode syntaxNode, DiagnosticBag diagnostics) + internal void EmitArrayBlockInitializer(ImmutableArray data, SyntaxNode syntaxNode) { // Emit the call to RuntimeHelpers.InitializeArray, creating the necessary metadata blob if there isn't // already one for this data. Note that this specifies an alignment of 1. This is valid regardless of @@ -100,14 +92,14 @@ internal void EmitArrayBlockInitializer(ImmutableArray data, SyntaxNode sy var initializeArray = module.GetInitArrayHelper(); // map a field to the block (that makes it addressable via a token). - var field = module.GetFieldForData(data, alignment: 1, syntaxNode, diagnostics); + var field = module.GetFieldForData(data, alignment: 1, syntaxNode, _diagnostics); // emit call to the helper EmitOpCode(ILOpCode.Dup); //array EmitOpCode(ILOpCode.Ldtoken); - EmitToken(field, syntaxNode, diagnostics); //block + EmitToken(field, syntaxNode); //block EmitOpCode(ILOpCode.Call, -2); - EmitToken(initializeArray, syntaxNode, diagnostics); + EmitToken(initializeArray, syntaxNode); } /// @@ -211,6 +203,7 @@ internal void EmitBranch(ILOpCode code, object label, ILOpCode revOpCode = ILOpC /// /// Primary method for emitting string switch jump table /// + /// Associated syntax for diagnostic reporting. /// switch case labels /// fall through label for the jump table /// Local holding the value to switch on. @@ -227,6 +220,7 @@ internal void EmitBranch(ILOpCode code, object label, ILOpCode revOpCode = ILOpC /// Delegate to compute string hash consistent with value of keyHash. /// internal void EmitStringSwitchJumpTable( + SyntaxNode syntax, KeyValuePair[] caseLabels, object fallThroughLabel, LocalOrParameter key, @@ -238,6 +232,7 @@ internal void EmitStringSwitchJumpTable( var emitter = new SwitchStringJumpTableEmitter( this, + syntax, key, caseLabels, fallThroughLabel, @@ -257,11 +252,13 @@ internal void EmitStringSwitchJumpTable( /// This value has already been loaded onto the execution stack. /// /// Primitive type code of switch key. + /// Associated syntax for error reporting. internal void EmitIntegerSwitchJumpTable( KeyValuePair[] caseLabels, object fallThroughLabel, LocalOrParameter key, - Cci.PrimitiveTypeCode keyTypeCode) + Cci.PrimitiveTypeCode keyTypeCode, + SyntaxNode syntax) { Debug.Assert(caseLabels.Length > 0); Debug.Assert(keyTypeCode != Cci.PrimitiveTypeCode.String); @@ -270,7 +267,7 @@ internal void EmitIntegerSwitchJumpTable( // CONSIDER: Currently, only purpose of creating this caseLabels array is for Emitting the jump table. // CONSIDER: If this requirement changes, we may want to pass in ArrayBuilder> instead. - var emitter = new SwitchIntegralJumpTableEmitter(this, caseLabels, fallThroughLabel, keyTypeCode, key); + var emitter = new SwitchIntegralJumpTableEmitter(this, syntax, caseLabels, fallThroughLabel, keyTypeCode, key); emitter.EmitJumpTable(); } @@ -360,7 +357,7 @@ private BasicBlock FinishFilterCondition() /// /// Generates code that creates an instance of multidimensional array /// - internal void EmitArrayCreation(Microsoft.Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode, DiagnosticBag diagnostics) + internal void EmitArrayCreation(Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode) { Debug.Assert(!arrayType.IsSZArray, "should be used only with multidimensional arrays"); @@ -368,13 +365,13 @@ internal void EmitArrayCreation(Microsoft.Cci.IArrayTypeReference arrayType, Syn // idx1, idx2 --> array this.EmitOpCode(ILOpCode.Newobj, 1 - (int)arrayType.Rank); - this.EmitToken(ctor, syntaxNode, diagnostics); + this.EmitToken(ctor, syntaxNode); } /// /// Generates code that loads an element of a multidimensional array /// - internal void EmitArrayElementLoad(Microsoft.Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode, DiagnosticBag diagnostics) + internal void EmitArrayElementLoad(Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode) { Debug.Assert(!arrayType.IsSZArray, "should be used only with multidimensional arrays"); @@ -382,13 +379,13 @@ internal void EmitArrayElementLoad(Microsoft.Cci.IArrayTypeReference arrayType, // this, idx1, idx2 --> value this.EmitOpCode(ILOpCode.Call, -(int)arrayType.Rank); - this.EmitToken(load, syntaxNode, diagnostics); + this.EmitToken(load, syntaxNode); } /// /// Generates code that loads an address of an element of a multidimensional array. /// - internal void EmitArrayElementAddress(Microsoft.Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode, DiagnosticBag diagnostics) + internal void EmitArrayElementAddress(Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode) { Debug.Assert(!arrayType.IsSZArray, "should be used only with multidimensional arrays"); @@ -396,13 +393,13 @@ internal void EmitArrayElementAddress(Microsoft.Cci.IArrayTypeReference arrayTyp // this, idx1, idx2 --> &value this.EmitOpCode(ILOpCode.Call, -(int)arrayType.Rank); - this.EmitToken(address, syntaxNode, diagnostics); + this.EmitToken(address, syntaxNode); } /// /// Generates code that stores an element of a multidimensional array. /// - internal void EmitArrayElementStore(Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode, DiagnosticBag diagnostics) + internal void EmitArrayElementStore(Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode) { Debug.Assert(!arrayType.IsSZArray, "should be used only with multidimensional arrays"); @@ -410,7 +407,7 @@ internal void EmitArrayElementStore(Cci.IArrayTypeReference arrayType, SyntaxNod // this, idx1, idx2, value --> void this.EmitOpCode(ILOpCode.Call, -(2 + (int)arrayType.Rank)); - this.EmitToken(store, syntaxNode, diagnostics); + this.EmitToken(store, syntaxNode); } internal void EmitLoad(LocalOrParameter localOrParameter) @@ -563,7 +560,7 @@ internal void EmitStoreArgumentOpcode(int argNumber) } } - internal void EmitConstantValue(ConstantValue value) + internal void EmitConstantValue(ConstantValue value, SyntaxNode? syntaxNode) { ConstantValueTypeDiscriminator discriminator = value.Discriminator; @@ -608,7 +605,7 @@ internal void EmitConstantValue(ConstantValue value) EmitDoubleConstant(value.DoubleValue); break; case ConstantValueTypeDiscriminator.String: - EmitStringConstant(value.StringValue); + EmitStringConstant(value.StringValue, syntaxNode); break; case ConstantValueTypeDiscriminator.Boolean: EmitBoolConstant(value.BooleanValue); @@ -734,16 +731,70 @@ internal void EmitNullConstant() EmitOpCode(ILOpCode.Ldnull); } - internal void EmitStringConstant(string? value) + internal void EmitStringConstant(string? value, SyntaxNode? syntax) { if (value == null) { EmitNullConstant(); + return; } - else + + // If the length is greater than the specified threshold try ldsfld first and fall back to ldstr. + // Otherwise, try emit ldstr and fall back to ldsfld if emitting EnC delta and the heap is already full. + bool success = (value.Length > module.CommonCompilation.DataSectionStringLiteralThreshold) + ? tryEmitLoadField() || tryEmitLoadString() + : tryEmitLoadString() || (module.PreviousGeneration != null && tryEmitLoadField()); + + if (!success) + { + // emit null to balance eval stack + EmitNullConstant(); + + var messageProvider = module.CommonCompilation.MessageProvider; + int code = module.PreviousGeneration != null ? messageProvider.ERR_TooManyUserStrings_RestartRequired : messageProvider.ERR_TooManyUserStrings; + _diagnostics.Add(messageProvider.CreateDiagnostic(code, syntax?.Location ?? Location.None)); + } + + bool tryEmitLoadString() + { + if (module.TryGetFakeStringTokenForIL(value, out uint token)) + { + EmitOpCode(ILOpCode.Ldstr); + GetCurrentWriter().WriteUInt32(token); + return true; + } + + return false; + } + + bool tryEmitLoadField() { - EmitOpCode(ILOpCode.Ldstr); - EmitToken(value); + var field = tryGetOrCreateField(); + if (field != null) + { + EmitOpCode(ILOpCode.Ldsfld); + EmitToken(field, syntax); + return true; + } + + return false; + } + + Cci.IFieldReference? tryGetOrCreateField() + { + if (!module.FieldRvaSupported) + { + return null; + } + + // Binder should have reported use-site errors for these members. + if (module.CommonCompilation.CommonGetWellKnownTypeMember(WellKnownMember.System_Text_Encoding__get_UTF8) == null || + module.CommonCompilation.CommonGetWellKnownTypeMember(WellKnownMember.System_Text_Encoding__GetString) == null) + { + return null; + } + + return module.TryGetOrCreateFieldForStringValue(value, syntax, _diagnostics); } } diff --git a/src/Compilers/Core/Portable/CodeGen/ITokenDeferral.cs b/src/Compilers/Core/Portable/CodeGen/ITokenDeferral.cs deleted file mode 100644 index c11dc6c21a3e4..0000000000000 --- a/src/Compilers/Core/Portable/CodeGen/ITokenDeferral.cs +++ /dev/null @@ -1,34 +0,0 @@ -// 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.Immutable; - -namespace Microsoft.CodeAnalysis.CodeGen -{ - internal interface ITokenDeferral - { - uint GetFakeStringTokenForIL(string value); - uint GetFakeSymbolTokenForIL(Cci.IReference value, SyntaxNode? syntaxNode, DiagnosticBag diagnostics); - uint GetFakeSymbolTokenForIL(Cci.ISignature value, SyntaxNode? syntaxNode, DiagnosticBag diagnostics); - uint GetSourceDocumentIndexForIL(Cci.DebugSourceDocument document); - - Cci.IFieldReference GetFieldForData(ImmutableArray data, ushort alignment, SyntaxNode syntaxNode, DiagnosticBag diagnostics); - - /// Gets a field that may be used to lazily cache an array created to store the specified data. - /// This is used to cache an array created with the data passed to . - Cci.IFieldReference GetArrayCachingFieldForData(ImmutableArray data, Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode, DiagnosticBag diagnostics); - - Cci.IFieldReference GetArrayCachingFieldForConstants(ImmutableArray constants, Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode, DiagnosticBag diagnostics); - - Cci.IMethodReference GetInitArrayHelper(); - - string GetStringFromToken(uint token); - /// - /// Gets the or corresponding to this token. - /// - object GetReferenceFromToken(uint token); - - ArrayMethods ArrayMethods { get; } - } -} diff --git a/src/Compilers/Core/Portable/CodeGen/MethodBody.cs b/src/Compilers/Core/Portable/CodeGen/MethodBody.cs index be2d425d5d0d4..4bc97bba46a32 100644 --- a/src/Compilers/Core/Portable/CodeGen/MethodBody.cs +++ b/src/Compilers/Core/Portable/CodeGen/MethodBody.cs @@ -26,11 +26,11 @@ internal sealed class MethodBody : Cci.IMethodBody // Debug information emitted to Release & Debug PDBs supporting the debugger, EEs and other tools: private readonly ImmutableArray _sequencePoints; private readonly ImmutableArray _localScopes; - private readonly Cci.IImportScope _importScopeOpt; - private readonly string _stateMachineTypeNameOpt; + private readonly Cci.IImportScope? _importScopeOpt; + private readonly string? _stateMachineTypeNameOpt; private readonly ImmutableArray _stateMachineHoistedLocalScopes; private readonly bool _hasDynamicLocalVariables; - private readonly StateMachineMoveNextBodyDebugInfo _stateMachineMoveNextDebugInfoOpt; + private readonly StateMachineMoveNextBodyDebugInfo? _stateMachineMoveNextDebugInfoOpt; // Debug information emitted to Debug PDBs supporting EnC: private readonly DebugId _methodId; @@ -54,23 +54,23 @@ public MethodBody( Cci.IMethodDefinition parent, DebugId methodId, ImmutableArray locals, - SequencePointList sequencePoints, - DebugDocumentProvider debugDocumentProvider, + SequencePointList? sequencePoints, + DebugDocumentProvider? debugDocumentProvider, ImmutableArray exceptionHandlers, bool areLocalsZeroed, bool hasStackalloc, ImmutableArray localScopes, bool hasDynamicLocalVariables, - Cci.IImportScope importScopeOpt, + Cci.IImportScope? importScopeOpt, ImmutableArray lambdaDebugInfo, ImmutableArray orderedLambdaRuntimeRudeEdits, ImmutableArray closureDebugInfo, - string stateMachineTypeNameOpt, + string? stateMachineTypeNameOpt, ImmutableArray stateMachineHoistedLocalScopes, ImmutableArray stateMachineHoistedLocalSlots, ImmutableArray stateMachineAwaiterSlots, StateMachineStatesDebugInfo stateMachineStatesDebugInfo, - StateMachineMoveNextBodyDebugInfo stateMachineMoveNextDebugInfoOpt, + StateMachineMoveNextBodyDebugInfo? stateMachineMoveNextDebugInfoOpt, ImmutableArray codeCoverageSpans, bool isPrimaryConstructor) { @@ -103,13 +103,15 @@ public MethodBody( _isPrimaryConstructor = isPrimaryConstructor; } - private static ImmutableArray GetSequencePoints(SequencePointList? sequencePoints, DebugDocumentProvider debugDocumentProvider) + private static ImmutableArray GetSequencePoints(SequencePointList? sequencePoints, DebugDocumentProvider? debugDocumentProvider) { if (sequencePoints == null || sequencePoints.IsEmpty) { return ImmutableArray.Empty; } + Debug.Assert(debugDocumentProvider != null); + var sequencePointsBuilder = ArrayBuilder.GetInstance(); sequencePoints.GetSequencePoints(debugDocumentProvider, sequencePointsBuilder); return sequencePointsBuilder.ToImmutableAndFree(); @@ -125,7 +127,7 @@ public MethodBody( Cci.IMethodDefinition Cci.IMethodBody.MethodDefinition => _parent; - StateMachineMoveNextBodyDebugInfo Cci.IMethodBody.MoveNextBodyInfo => _stateMachineMoveNextDebugInfoOpt; + StateMachineMoveNextBodyDebugInfo? Cci.IMethodBody.MoveNextBodyInfo => _stateMachineMoveNextDebugInfoOpt; ushort Cci.IMethodBody.MaxStack => _maxStack; @@ -138,9 +140,9 @@ public MethodBody( /// /// This is a list of the using directives that were in scope for this method body. /// - Cci.IImportScope Cci.IMethodBody.ImportScope => _importScopeOpt; + Cci.IImportScope? Cci.IMethodBody.ImportScope => _importScopeOpt; - string Cci.IMethodBody.StateMachineTypeName => _stateMachineTypeNameOpt; + string? Cci.IMethodBody.StateMachineTypeName => _stateMachineTypeNameOpt; ImmutableArray Cci.IMethodBody.StateMachineHoistedLocalScopes => _stateMachineHoistedLocalScopes; diff --git a/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs b/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs index 87b9df89e731c..3c820cdd06a80 100644 --- a/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs +++ b/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs @@ -327,7 +327,7 @@ internal MappedField GetOrAddDataField(ImmutableArray data, ushort alignme internal static Cci.IFieldReference? TryGetOrCreateFieldForStringValue( string text, CommonPEModuleBuilder moduleBuilder, - SyntaxNode syntaxNode, + SyntaxNode? syntaxNode, DiagnosticBag diagnostics) { if (!text.TryGetUtf8ByteRepresentation(out byte[]? data, out _)) @@ -354,7 +354,7 @@ internal MappedField GetOrAddDataField(ImmutableArray data, ushort alignme var messageProvider = @this.ModuleBuilder.CommonCompilation.MessageProvider; diagnostics.Add(messageProvider.CreateDiagnostic( messageProvider.ERR_DataSectionStringLiteralHashCollision, - syntaxNode.GetLocation(), + syntaxNode?.GetLocation() ?? Location.None, previousText[..Math.Min(previousText.Length, 500)])); } @@ -382,7 +382,7 @@ private Cci.IMethodDefinition GetOrSynthesizeBytesToStringHelper(DiagnosticBag d var encodingGetString = getWellKnownTypeMember(compilation, WellKnownMember.System_Text_Encoding__GetString); TryAddSynthesizedMethod(BytesToStringHelper.Create( - moduleBuilder: (ITokenDeferral)ModuleBuilder, + moduleBuilder: ModuleBuilder, containingType: this, encodingUtf8: encodingUtf8, encodingGetString: encodingGetString, @@ -743,14 +743,14 @@ public DataSectionStringType( var stringField = new DataSectionStringField("s", this); - var staticConstructor = synthesizeStaticConstructor((ITokenDeferral)containingType.ModuleBuilder, containingType, dataField, stringField, bytesToStringHelper, diagnostics); + var staticConstructor = synthesizeStaticConstructor(containingType.ModuleBuilder, this, dataField, stringField, bytesToStringHelper, diagnostics); _fields = [stringField]; _methods = [staticConstructor]; static Cci.IMethodDefinition synthesizeStaticConstructor( - ITokenDeferral module, - Cci.INamespaceTypeDefinition containingType, + CommonPEModuleBuilder module, + Cci.ITypeDefinition containingType, MappedField dataField, DataSectionStringField stringField, Cci.IMethodDefinition bytesToStringHelper, @@ -759,23 +759,24 @@ static Cci.IMethodDefinition synthesizeStaticConstructor( var ilBuilder = new ILBuilder( module, new LocalSlotManager(slotAllocator: null), + diagnostics, OptimizationLevel.Release, areLocalsZeroed: false); // Push the `byte*` field's address. ilBuilder.EmitOpCode(ILOpCode.Ldsflda); - ilBuilder.EmitToken(dataField, null, diagnostics); + ilBuilder.EmitToken(dataField, null); // Push the byte size. ilBuilder.EmitIntConstant(dataField.MappedData.Length); // Call `.BytesToString(byte*, int)`. ilBuilder.EmitOpCode(ILOpCode.Call, -1); - ilBuilder.EmitToken(bytesToStringHelper, null, diagnostics); + ilBuilder.EmitToken(bytesToStringHelper, null); // Store into the corresponding `string` field. ilBuilder.EmitOpCode(ILOpCode.Stsfld); - ilBuilder.EmitToken(stringField, null, diagnostics); + ilBuilder.EmitToken(stringField, null); ilBuilder.EmitRet(isVoid: true); ilBuilder.Realize(); @@ -1173,7 +1174,7 @@ private BytesToStringHelper( } public static BytesToStringHelper Create( - ITokenDeferral moduleBuilder, + CommonPEModuleBuilder moduleBuilder, Cci.INamespaceTypeDefinition containingType, Cci.IMethodReference encodingUtf8, Cci.IMethodReference encodingGetString, @@ -1182,12 +1183,13 @@ public static BytesToStringHelper Create( var ilBuilder = new ILBuilder( moduleBuilder, new LocalSlotManager(slotAllocator: null), + diagnostics, OptimizationLevel.Release, areLocalsZeroed: false); // Call `Encoding.get_UTF8()`. ilBuilder.EmitOpCode(ILOpCode.Call, 1); - ilBuilder.EmitToken(encodingUtf8, null, diagnostics); + ilBuilder.EmitToken(encodingUtf8, null); // Push the `byte*`. ilBuilder.EmitOpCode(ILOpCode.Ldarg_0); @@ -1197,7 +1199,7 @@ public static BytesToStringHelper Create( // Call `Encoding.GetString(byte*, int)`. ilBuilder.EmitOpCode(ILOpCode.Callvirt, -2); - ilBuilder.EmitToken(encodingGetString, null, diagnostics); + ilBuilder.EmitToken(encodingGetString, null); // Return. ilBuilder.EmitRet(isVoid: false); diff --git a/src/Compilers/Core/Portable/CodeGen/StringTokenMap.cs b/src/Compilers/Core/Portable/CodeGen/StringTokenMap.cs new file mode 100644 index 0000000000000..a6153ce286748 --- /dev/null +++ b/src/Compilers/Core/Portable/CodeGen/StringTokenMap.cs @@ -0,0 +1,71 @@ +// 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.Concurrent; +using System.Collections.Generic; +using Microsoft.CodeAnalysis.PooledObjects; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CodeGen; + +/// +/// Handles storage of strings referenced via tokens in metadata. When values are stored +/// they are uniquely "associated" with fake tokens, which are basically sequential numbers. +/// IL gen will use these fake tokens during codegen and later, when actual values +/// are known, the method bodies will be patched. +/// +internal sealed class StringTokenMap(int initialHeapSize) +{ + private readonly ConcurrentDictionary _valueToToken = new ConcurrentDictionary(ReferenceEqualityComparer.Instance); + private readonly ArrayBuilder _uniqueValues = []; + private int _heapSize = initialHeapSize; + + public bool TryGetOrAddToken(string value, out uint token) + { + // NOTE: cannot use GetOrAdd here since _uniqueValues and _valueToToken must be in sync + // so if we do need to add we have to take a lock and modify both collections. + if (_valueToToken.TryGetValue(value, out token)) + { + return true; + } + + lock (_uniqueValues) + { + if (_valueToToken.TryGetValue(value, out token)) + { + return true; + } + + // String can span beyond the heap limit, but must start within the limit. + if (_heapSize > MetadataHelpers.UserStringHeapCapacity) + { + return false; + } + + _heapSize += MetadataHelpers.GetUserStringBlobSize(value); + + token = (uint)_uniqueValues.Count; + _uniqueValues.Add(value); + _valueToToken.Add(value, token); + + return true; + } + } + + public string GetValue(uint token) + { + lock (_uniqueValues) + { + return _uniqueValues[(int)token]; + } + } + + public string[] CopyValues() + { + lock (_uniqueValues) + { + return _uniqueValues.ToArray(); + } + } +} diff --git a/src/Compilers/Core/Portable/CodeGen/SwitchIntegralJumpTableEmitter.cs b/src/Compilers/Core/Portable/CodeGen/SwitchIntegralJumpTableEmitter.cs index 9b57ad3e7bb43..d6cbaed255843 100644 --- a/src/Compilers/Core/Portable/CodeGen/SwitchIntegralJumpTableEmitter.cs +++ b/src/Compilers/Core/Portable/CodeGen/SwitchIntegralJumpTableEmitter.cs @@ -19,6 +19,11 @@ internal partial struct SwitchIntegralJumpTableEmitter { private readonly ILBuilder _builder; + /// + /// Associated syntax for diagnostic reporting. + /// + private readonly SyntaxNode _syntax; + /// /// Switch key for the jump table /// @@ -48,12 +53,14 @@ internal partial struct SwitchIntegralJumpTableEmitter internal SwitchIntegralJumpTableEmitter( ILBuilder builder, + SyntaxNode syntax, KeyValuePair[] caseLabels, object fallThroughLabel, Cci.PrimitiveTypeCode keyTypeCode, LocalOrParameter key) { _builder = builder; + _syntax = syntax; _key = key; _keyTypeCode = keyTypeCode; _fallThroughLabel = fallThroughLabel; @@ -423,7 +430,7 @@ private void EmitCondBranchForSwitch(ILOpCode branchCode, ConstantValue constant // branch branchCode targetLabel _builder.EmitLoad(_key); - _builder.EmitConstantValue(constant); + _builder.EmitConstantValue(constant, _syntax); _builder.EmitBranch(branchCode, targetLabel, GetReverseBranchCode(branchCode)); } @@ -443,7 +450,7 @@ private void EmitEqBranchForSwitch(ConstantValue constant, object targetLabel) } else { - _builder.EmitConstantValue(constant); + _builder.EmitConstantValue(constant, _syntax); _builder.EmitBranch(ILOpCode.Beq, targetLabel); } } @@ -458,7 +465,7 @@ private void EmitRangeCheckedBranch(ConstantValue startConstant, ConstantValue e // sub if (!startConstant.IsDefaultValue) { - _builder.EmitConstantValue(startConstant); + _builder.EmitConstantValue(startConstant, _syntax); _builder.EmitOpCode(ILOpCode.Sub); } @@ -521,7 +528,7 @@ private void EmitNormalizedSwitchKey(ConstantValue startConstant, ConstantValue // sub if (!startConstant.IsDefaultValue) { - _builder.EmitConstantValue(startConstant); + _builder.EmitConstantValue(startConstant, _syntax); _builder.EmitOpCode(ILOpCode.Sub); } diff --git a/src/Compilers/Core/Portable/CodeGen/SwitchStringJumpTableEmitter.cs b/src/Compilers/Core/Portable/CodeGen/SwitchStringJumpTableEmitter.cs index d496e0a67be12..939427eac6981 100644 --- a/src/Compilers/Core/Portable/CodeGen/SwitchStringJumpTableEmitter.cs +++ b/src/Compilers/Core/Portable/CodeGen/SwitchStringJumpTableEmitter.cs @@ -19,6 +19,11 @@ internal readonly struct SwitchStringJumpTableEmitter { private readonly ILBuilder _builder; + /// + /// Associated syntax for diagnostic reporting. + /// + private readonly SyntaxNode _syntax; + /// /// Switch key for the jump table /// @@ -65,6 +70,7 @@ internal readonly struct SwitchStringJumpTableEmitter internal SwitchStringJumpTableEmitter( ILBuilder builder, + SyntaxNode syntax, LocalOrParameter key, KeyValuePair[] caseLabels, object fallThroughLabel, @@ -76,6 +82,7 @@ internal SwitchStringJumpTableEmitter( RoslynDebug.Assert(emitStringCondBranchDelegate != null); _builder = builder; + _syntax = syntax; _key = key; _caseLabels = caseLabels; _fallThroughLabel = fallThroughLabel; @@ -148,6 +155,7 @@ private Dictionary EmitHashBucketJumpTable(Dictionary EmitDifference(baseline, edits, isAddedSymbol, metadataStream, ilStream, pdbStream, EmitDifferenceOptions.Default, cancellationToken); + + /// + /// Emit the differences between the compilation and the previous generation + /// for Edit and Continue. The differences are expressed as added and changed + /// symbols, and are emitted as metadata, IL, and PDB deltas. A representation + /// of the current compilation is returned as an EmitBaseline for use in a + /// subsequent Edit and Continue. + /// + public EmitDifferenceResult EmitDifference( + EmitBaseline baseline, + IEnumerable edits, + Func isAddedSymbol, + Stream metadataStream, + Stream ilStream, + Stream pdbStream, + EmitDifferenceOptions options, + CancellationToken cancellationToken = default(CancellationToken)) { if (baseline == null) { @@ -3128,7 +3146,7 @@ public EmitDifferenceResult EmitDifference( throw new ArgumentNullException(nameof(pdbStream)); } - return this.EmitDifference(baseline, edits, isAddedSymbol, metadataStream, ilStream, pdbStream, testData: null, cancellationToken); + return this.EmitDifference(baseline, edits, isAddedSymbol, metadataStream, ilStream, pdbStream, options, testData: null, cancellationToken); } #pragma warning restore RS0026 // Do not add multiple public overloads with optional parameters @@ -3139,6 +3157,7 @@ internal abstract EmitDifferenceResult EmitDifference( Stream metadataStream, Stream ilStream, Stream pdbStream, + EmitDifferenceOptions options, CompilationTestData? testData, CancellationToken cancellationToken); @@ -3422,7 +3441,6 @@ internal static bool SerializePeToStream( internal EmitBaseline? SerializeToDeltaStreams( CommonPEModuleBuilder moduleBeingBuilt, DefinitionMap definitionMap, - SymbolChanges changes, Stream metadataStream, Stream ilStream, Stream pdbStream, @@ -3442,7 +3460,6 @@ internal static bool SerializePeToStream( using (nativePdbWriter) { var context = new EmitContext(moduleBeingBuilt, diagnostics, metadataOnly: false, includePrivateMembers: true); - var deletedMethodDefs = DeltaMetadataWriter.CreateDeletedMethodsDefs(context, changes); // Map the definitions from the previous compilation to the current compilation. // This must be done after compiling since synthesized definitions (generated when compiling method bodies) @@ -3460,8 +3477,6 @@ internal static bool SerializePeToStream( baseline, encId, definitionMap, - changes, - deletedMethodDefs, cancellationToken); moduleBeingBuilt.TestData?.SetMetadataWriter(writer); @@ -3497,7 +3512,7 @@ internal static bool SerializePeToStream( } finally { - foreach (var (_, builder) in deletedMethodDefs) + foreach (var (_, builder) in moduleBeingBuilt.GetDeletedMethodDefinitions()) { builder.Free(); } diff --git a/src/Compilers/Core/Portable/Compilation/EmitDifferenceOptions.cs b/src/Compilers/Core/Portable/Compilation/EmitDifferenceOptions.cs new file mode 100644 index 0000000000000..b793f7cad973c --- /dev/null +++ b/src/Compilers/Core/Portable/Compilation/EmitDifferenceOptions.cs @@ -0,0 +1,15 @@ +// 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. + +namespace Microsoft.CodeAnalysis.Emit; + +public readonly struct EmitDifferenceOptions() +{ + public static readonly EmitDifferenceOptions Default = new(); + + /// + /// True to emit FieldRva table entries. The runtime must support this feature. + /// + public bool EmitFieldRva { get; init; } +} diff --git a/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs b/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs index b662165fee496..6d3310c771bbb 100644 --- a/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs +++ b/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs @@ -239,6 +239,7 @@ public string GetIdForErrorCode(int errorCode) public abstract int ERR_MetadataNameTooLong { get; } public abstract int ERR_EncReferenceToAddedMember { get; } public abstract int ERR_TooManyUserStrings { get; } + public abstract int ERR_TooManyUserStrings_RestartRequired { get; } public abstract int ERR_PeWritingFailure { get; } public abstract int ERR_ModuleEmitFailure { get; } public abstract int ERR_EncUpdateFailedMissingSymbol { get; } diff --git a/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs b/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs index 84be01ad50e1e..e128038c6aa81 100644 --- a/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs +++ b/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs @@ -7,6 +7,8 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Contracts; using System.IO; using System.Linq; using System.Security.Cryptography; @@ -35,19 +37,23 @@ internal abstract class CommonPEModuleBuilder : Cci.IUnit, Cci.IModuleReference private readonly ConcurrentDictionary _methodBodyMap; private readonly TokenMap _referencesInILMap = new(); - private readonly ItemTokenMap _stringsInILMap = new(); + private readonly Lazy _stringsInILMap; private readonly ItemTokenMap _sourceDocumentsInILMap = new(); private ImmutableArray _lazyAssemblyReferenceAliases; private ImmutableArray _lazyManagedResources; private IEnumerable _embeddedTexts = SpecializedCollections.EmptyEnumerable(); + private ArrayMethods? _lazyArrayMethods; + + // Calculated when emitting EnC deltas. + private IReadOnlyDictionary>? _encDeletedMethodDefinitions; // Only set when running tests to allow inspection of the emitted data. internal CompilationTestData? TestData { get; private set; } internal EmitOptions EmitOptions { get; } - public CommonPEModuleBuilder( + protected CommonPEModuleBuilder( IEnumerable manifestResources, EmitOptions emitOptions, OutputKind outputKind, @@ -63,6 +69,7 @@ public CommonPEModuleBuilder( OutputKind = outputKind; SerializationProperties = serializationProperties; _methodBodyMap = new ConcurrentDictionary(ReferenceEqualityComparer.Instance); + _stringsInILMap = new Lazy(() => new StringTokenMap(PreviousGeneration?.UserStringStreamLength ?? 0)); EmitOptions = emitOptions; } @@ -74,6 +81,11 @@ public CommonPEModuleBuilder( /// public abstract SymbolChanges? EncSymbolChanges { get; } + /// + /// True if FieldRVA table is supported by the runtime. + /// + public abstract bool FieldRvaSupported { get; } + /// /// Previous EnC generation baseline, or null if this is not EnC delta. /// @@ -105,6 +117,27 @@ public CommonPEModuleBuilder( ///
public abstract INamedTypeSymbolInternal? GetUsedSynthesizedHotReloadExceptionType(); + /// + /// Creates definitions for deleted methods based on symbol changes if emitting EnC delta. + /// Must be called before . + /// + public void CreateDeletedMethodDefinitions(DiagnosticBag diagnosticBag) + { + Debug.Assert(_encDeletedMethodDefinitions == null); + + if (EncSymbolChanges != null) + { + var context = new EmitContext(this, diagnosticBag, metadataOnly: false, includePrivateMembers: true); + _encDeletedMethodDefinitions = DeltaMetadataWriter.CreateDeletedMethodsDefs(context, EncSymbolChanges); + } + } + + public IReadOnlyDictionary> GetDeletedMethodDefinitions() + { + Debug.Assert(_encDeletedMethodDefinitions != null); + return _encDeletedMethodDefinitions; + } + #nullable disable /// @@ -132,6 +165,11 @@ public CommonPEModuleBuilder( public abstract IEnumerable GetSourceAssemblySecurityAttributes(); public abstract IEnumerable GetSourceModuleAttributes(); internal abstract Cci.ICustomAttribute SynthesizeAttribute(WellKnownMember attributeConstructor); + public abstract Cci.IMethodReference GetInitArrayHelper(); + + public abstract Cci.IFieldReference GetFieldForData(ImmutableArray data, ushort alignment, SyntaxNode syntaxNode, DiagnosticBag diagnostics); + public abstract Cci.IFieldReference GetArrayCachingFieldForData(ImmutableArray data, Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode, DiagnosticBag diagnostics); + public abstract Cci.IFieldReference GetArrayCachingFieldForConstants(ImmutableArray constants, Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode, DiagnosticBag diagnostics); /// /// Public types defined in other modules making up this assembly and to which other assemblies may refer to via this assembly @@ -175,9 +213,35 @@ public CommonPEModuleBuilder( public abstract bool IsPlatformType(Cci.ITypeReference typeRef, Cci.PlatformType platformType); #nullable enable + public ArrayMethods ArrayMethods + { + get + { + ArrayMethods? result = _lazyArrayMethods; + + if (result == null) + { + result = new ArrayMethods(); + + if (Interlocked.CompareExchange(ref _lazyArrayMethods, result, null) != null) + { + result = _lazyArrayMethods; + } + } + + return result; + } + } + + /// + /// + /// + public Cci.IFieldReference? TryGetOrCreateFieldForStringValue(string text, SyntaxNode? syntaxNode, DiagnosticBag diagnostics) + => PrivateImplementationDetails.TryGetOrCreateFieldForStringValue(text, this, syntaxNode, diagnostics); + public abstract IEnumerable GetTopLevelTypeDefinitions(EmitContext context); - public IEnumerable GetTopLevelTypeDefinitionsCore(EmitContext context) + public IEnumerable GetTopLevelTypeDefinitionsExcludingNoPiaAndRootModule(EmitContext context, bool includePrivateImplementationDetails) { foreach (var typeDef in GetAnonymousTypeDefinitions(context)) { @@ -199,14 +263,17 @@ public CommonPEModuleBuilder( yield return typeDef; } - var privateImpl = GetFrozenPrivateImplementationDetails(); - if (privateImpl != null) + if (includePrivateImplementationDetails) { - yield return privateImpl; - - foreach (var typeDef in privateImpl.GetAdditionalTopLevelTypes()) + var privateImpl = GetFrozenPrivateImplementationDetails(); + if (privateImpl != null) { - yield return typeDef; + yield return privateImpl; + + foreach (var typeDef in privateImpl.GetAdditionalTopLevelTypes()) + { + yield return typeDef; + } } } } @@ -390,7 +457,7 @@ public Cci.IAssemblyReference GetContainingAssembly(EmitContext context) /// public string[] CopyStrings() { - return _stringsInILMap.CopyItems(); + return _stringsInILMap.Value.CopyValues(); } public uint GetFakeSymbolTokenForIL(Cci.IReference symbol, SyntaxNode syntaxNode, DiagnosticBag diagnostics) @@ -428,15 +495,11 @@ public object GetReferenceFromToken(uint token) return _referencesInILMap.GetItem(token); } - public uint GetFakeStringTokenForIL(string str) - { - return _stringsInILMap.GetOrAddTokenFor(str); - } + public bool TryGetFakeStringTokenForIL(string str, out uint token) + => _stringsInILMap.Value.TryGetOrAddToken(str, out token); public string GetStringFromToken(uint token) - { - return _stringsInILMap.GetItem(token); - } + => _stringsInILMap.Value.GetValue(token); public ReadOnlySpan ReferencesInIL() { @@ -577,7 +640,7 @@ public int GetTypeDefinitionGeneration(Cci.INamedTypeDefinition typeDef) /// /// Common base class for C# and VB PE module builder. /// - internal abstract class PEModuleBuilder : CommonPEModuleBuilder, ITokenDeferral + internal abstract class PEModuleBuilder : CommonPEModuleBuilder where TCompilation : Compilation where TSourceModuleSymbol : class, IModuleSymbolInternal where TAssemblySymbol : class, IAssemblySymbolInternal @@ -592,7 +655,6 @@ internal abstract class PEModuleBuilder _namesOfTopLevelTypes; internal readonly TModuleCompilationState CompilationState; @@ -686,7 +748,7 @@ protected bool ContainsTopLevelType(string fullEmittedName) VisitTopLevelType(typeReferenceIndexer, RootModuleType); yield return RootModuleType; - foreach (var typeDef in GetTopLevelTypeDefinitionsCore(context)) + foreach (var typeDef in GetTopLevelTypeDefinitionsExcludingNoPiaAndRootModule(context, includePrivateImplementationDetails: true)) { AddTopLevelType(names, typeDef); VisitTopLevelType(typeReferenceIndexer, typeDef); @@ -1018,7 +1080,7 @@ internal override ImmutableDictionary data, ushort alignment, SyntaxNode syntaxNode, DiagnosticBag diagnostics) + public sealed override Cci.IFieldReference GetFieldForData(ImmutableArray data, ushort alignment, SyntaxNode syntaxNode, DiagnosticBag diagnostics) { RoslynDebug.Assert(alignment is 1 or 2 or 4 or 8, $"Unexpected alignment: {alignment}"); @@ -1028,7 +1090,7 @@ Cci.IFieldReference ITokenDeferral.GetFieldForData(ImmutableArray data, us return privateImpl.GetOrAddDataField(data, alignment); } - Cci.IFieldReference ITokenDeferral.GetArrayCachingFieldForData(ImmutableArray data, Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode, DiagnosticBag diagnostics) + public sealed override Cci.IFieldReference GetArrayCachingFieldForData(ImmutableArray data, Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode, DiagnosticBag diagnostics) { var privateImpl = GetPrivateImplClass((TSyntaxNode)syntaxNode, diagnostics); @@ -1038,43 +1100,13 @@ Cci.IFieldReference ITokenDeferral.GetArrayCachingFieldForData(ImmutableArray constants, Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode, DiagnosticBag diagnostics) + public sealed override Cci.IFieldReference GetArrayCachingFieldForConstants(ImmutableArray constants, Cci.IArrayTypeReference arrayType, SyntaxNode syntaxNode, DiagnosticBag diagnostics) { var privateImpl = GetPrivateImplClass((TSyntaxNode)syntaxNode, diagnostics); var emitContext = new EmitContext(this, syntaxNode, diagnostics, metadataOnly: false, includePrivateMembers: true); return privateImpl.CreateArrayCachingField(constants, arrayType, emitContext); } - /// - /// - /// - public Cci.IFieldReference TryGetOrCreateFieldForStringValue(string text, TSyntaxNode syntaxNode, DiagnosticBag diagnostics) - { - return PrivateImplementationDetails.TryGetOrCreateFieldForStringValue(text, this, syntaxNode, diagnostics); - } - - public abstract Cci.IMethodReference GetInitArrayHelper(); - - public ArrayMethods ArrayMethods - { - get - { - ArrayMethods result = _lazyArrayMethods; - - if (result == null) - { - result = new ArrayMethods(); - - if (Interlocked.CompareExchange(ref _lazyArrayMethods, result, null) != null) - { - result = _lazyArrayMethods; - } - } - - return result; - } - } - #endregion #region Private Implementation Details Type diff --git a/src/Compilers/Core/Portable/Emit/EditAndContinue/DeletedMethodBody.cs b/src/Compilers/Core/Portable/Emit/EditAndContinue/DeletedMethodBody.cs index 72328ce901753..4ece9e7aa109b 100644 --- a/src/Compilers/Core/Portable/Emit/EditAndContinue/DeletedMethodBody.cs +++ b/src/Compilers/Core/Portable/Emit/EditAndContinue/DeletedMethodBody.cs @@ -43,7 +43,7 @@ internal sealed class DeletedMethodBody(IDeletedMethodDefinition methodDef, Immu public DebugId MethodId => default; - public ImmutableArray StateMachineHoistedLocalScopes => ImmutableArray.Empty; + public ImmutableArray StateMachineHoistedLocalScopes => default; public string StateMachineTypeName => null; @@ -68,7 +68,7 @@ public static ImmutableArray GetIL(EmitContext context, RuntimeRudeEdit? r { var hotReloadExceptionCtorDef = context.Module.GetOrCreateHotReloadExceptionConstructorDefinition(); - var builder = new ILBuilder((ITokenDeferral)context.Module, null, OptimizationLevel.Debug, false); + var builder = new ILBuilder(context.Module, localSlotManager: null, context.Diagnostics, OptimizationLevel.Debug, areLocalsZeroed: false); string message; int codeValue; @@ -84,12 +84,14 @@ public static ImmutableArray GetIL(EmitContext context, RuntimeRudeEdit? r codeValue = code.GetExceptionCodeValue(); } - builder.EmitStringConstant(message); + var syntaxNode = context.SyntaxNode; + + builder.EmitStringConstant(message, syntaxNode); builder.EmitIntConstant(codeValue); // consumes message and code, pushes the created exception object: builder.EmitOpCode(ILOpCode.Newobj, stackAdjustment: -1); - builder.EmitToken(hotReloadExceptionCtorDef.GetCciAdapter(), context.SyntaxNode!, context.Diagnostics); + builder.EmitToken(hotReloadExceptionCtorDef.GetCciAdapter(), syntaxNode); builder.EmitThrow(isRethrow: false); builder.Realize(); diff --git a/src/Compilers/Core/Portable/Emit/EditAndContinue/DeltaMetadataWriter.cs b/src/Compilers/Core/Portable/Emit/EditAndContinue/DeltaMetadataWriter.cs index 797c54af87e97..96a218ede1dcf 100644 --- a/src/Compilers/Core/Portable/Emit/EditAndContinue/DeltaMetadataWriter.cs +++ b/src/Compilers/Core/Portable/Emit/EditAndContinue/DeltaMetadataWriter.cs @@ -26,7 +26,6 @@ internal sealed class DeltaMetadataWriter : MetadataWriter private readonly EmitBaseline _previousGeneration; private readonly Guid _encId; private readonly DefinitionMap _definitionMap; - private readonly SymbolChanges _changes; /// /// Type definitions containing any changes (includes added types). @@ -73,8 +72,6 @@ public DeltaMetadataWriter( EmitBaseline previousGeneration, Guid encId, DefinitionMap definitionMap, - SymbolChanges changes, - IReadOnlyDictionary> deletedMethodDefs, CancellationToken cancellationToken) : base(metadata: MakeTablesBuilder(previousGeneration), debugMetadataOpt: (context.Module.DebugInformationFormat == DebugInformationFormat.PortablePdb) ? new MetadataBuilder() : null, @@ -87,20 +84,20 @@ public DeltaMetadataWriter( cancellationToken: cancellationToken) { Debug.Assert(previousGeneration != null); - Debug.Assert(encId != default(Guid)); + Debug.Assert(encId != default); Debug.Assert(encId != previousGeneration.EncId); Debug.Assert(context.Module.DebugInformationFormat != DebugInformationFormat.Embedded); + Debug.Assert(context.Module.EncSymbolChanges != null); _previousGeneration = previousGeneration; _encId = encId; _definitionMap = definitionMap; - _changes = changes; var sizes = previousGeneration.TableSizes; _changedTypeDefs = new List(); _deletedTypeMembers = new Dictionary>(ReferenceEqualityComparer.Instance); - _deletedMethodDefs = deletedMethodDefs; + _deletedMethodDefs = context.Module.GetDeletedMethodDefinitions(); _typeDefs = new DefinitionIndex(this.TryGetExistingTypeDefIndex, sizes[(int)TableIndex.TypeDef]); _eventDefs = new DefinitionIndex(this.TryGetExistingEventDefIndex, sizes[(int)TableIndex.Event]); _fieldDefs = new DefinitionIndex(this.TryGetExistingFieldDefIndex, sizes[(int)TableIndex.Field]); @@ -130,13 +127,27 @@ public DeltaMetadataWriter( _addedOrChangedMethods = new Dictionary(Cci.SymbolEquivalentEqualityComparer.Instance); } + public SymbolChanges Changes + { + get + { + var changes = Context.Module.EncSymbolChanges; + Debug.Assert(changes != null); + return changes; + } + } + private static MetadataBuilder MakeTablesBuilder(EmitBaseline previousGeneration) { return new MetadataBuilder( - previousGeneration.UserStringStreamLength, - previousGeneration.StringStreamLength, - previousGeneration.BlobStreamLength, - previousGeneration.GuidStreamLength); + // Any string on the #UserString heap must start at an offset less than 2^24 (limited by token size). + // The baseline #UserString heap size might exceed this limit as long as the last string it contains starts within the limit. + // If the limit is exceeded we can't add any more strings in the delta heap (they would start beyond the limit), but we still can emit deltas. + // The check in MetadataBuilder constructor is enforcing the limit, but it should really only throw when a new string is added. + userStringHeapStartOffset: Math.Min(MetadataHelpers.UserStringHeapCapacity, previousGeneration.UserStringStreamLength), + stringHeapStartOffset: previousGeneration.StringStreamLength, + blobHeapStartOffset: previousGeneration.BlobStreamLength, + guidHeapStartOffset: previousGeneration.GuidStreamLength); } private ImmutableArray GetDeltaTableSizes(ImmutableArray rowCounts) @@ -196,7 +207,7 @@ internal EmitBaseline GetDelta(Compilation compilation, Guid encId, MetadataSize var generationOrdinals = CreateDictionary(_previousGeneration.GenerationOrdinals, SymbolEquivalentEqualityComparer.Instance); foreach (var (addedType, _) in addedTypes) { - if (_changes.IsReplacedDef(addedType)) + if (Changes.IsReplacedDef(addedType)) { generationOrdinals[addedType] = currentGenerationOrdinal; } @@ -496,7 +507,9 @@ internal static IReadOnlyDictionary>(ReferenceEqualityComparer.Instance); var typesUsedByDeletedMembers = new Dictionary(ReferenceEqualityComparer.Instance); - foreach (var typeDef in context.Module.GetTopLevelTypeDefinitions(context)) + // Skip PrivateImplementationDetails - we should only be adding new members to it. + // Emitting deleted method body may also produce new PrivateImplementationDetails members. + foreach (var typeDef in context.Module.GetTopLevelTypeDefinitionsExcludingNoPiaAndRootModule(context, includePrivateImplementationDetails: false)) { recurse(typeDef); } @@ -588,7 +601,7 @@ void addDeletedClosureMethods(IMethodSymbolInternal oldMethod, ImmutableArray rowCounts, ArrayBuilder TableIndex.ModuleRef, TableIndex.TypeSpec, TableIndex.ImplMap, - // FieldRva is not needed since we do not emit fields with explicit mapping during EnC. - // https://github.com/dotnet/roslyn/issues/69480 - //TableIndex.FieldRva, + TableIndex.FieldRva, TableIndex.EncLog, TableIndex.EncMap, TableIndex.Assembly, @@ -1824,7 +1835,7 @@ private sealed class DeltaReferenceIndexer : ReferenceIndexer public DeltaReferenceIndexer(DeltaMetadataWriter writer) : base(writer) { - _changes = writer._changes; + _changes = writer.Changes; _deletedTypeMembers = writer._deletedTypeMembers; } diff --git a/src/Compilers/Core/Portable/MetadataReader/MetadataHelpers.cs b/src/Compilers/Core/Portable/MetadataReader/MetadataHelpers.cs index 74cec5acf2eec..7fce63b6d05b6 100644 --- a/src/Compilers/Core/Portable/MetadataReader/MetadataHelpers.cs +++ b/src/Compilers/Core/Portable/MetadataReader/MetadataHelpers.cs @@ -19,6 +19,17 @@ namespace Microsoft.CodeAnalysis { internal static class MetadataHelpers { + /// + /// Once the #UserString heap reaches this size, we can't emit any more string literals to it. + /// + /// The max number of bytes that can fit into #US the heap is 2^29 - 1, + /// but each string also needs to have an offset that's at most 0xffffff (2^24 - 1) to be addressable by a token. + /// First byte of the heap is reserved (0), hence there is 2 ^ 24 - 2 bytes available for user strings. + /// + /// See https://github.com/dotnet/runtime/blob/2bd17019c1c01a6bf17a2de244ff92591fc3c334/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs#L82 + /// + internal const int UserStringHeapCapacity = 0xfffffe; + // https://github.com/dotnet/roslyn/issues/73548: // Remove this constant and refer to GenericParameterAttributes.AllowByRefLike directly once the new enum member becomes available. // See // https://github.com/dotnet/runtime/issues/68002#issuecomment-1942166436 for more details. @@ -1066,5 +1077,35 @@ internal static string MangleForTypeNameIfNeeded(string moduleName) return pooledStrBuilder.ToStringAndFree(); } + + /// + /// Calculates the number of bytes written on #UserHeap for the given string. + /// See https://github.com/dotnet/runtime/blob/5bfc0bec9d627c946f154dd99103a393d278f841/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobBuilder.cs#L1044 + /// + internal static int GetUserStringBlobSize(string value) + { + var byteLength = value.Length * 2 + 1; + return GetCompressedIntegerSize(byteLength) + byteLength; + } + + /// + /// See https://github.com/dotnet/runtime/blob/5bfc0bec9d627c946f154dd99103a393d278f841/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobWriterImpl.cs#L16 + /// + private static int GetCompressedIntegerSize(int value) + { + Debug.Assert(value <= 0x1fffffff); + + if (value <= 0x7f) + { + return 1; + } + + if (value <= 0x3fff) + { + return 2; + } + + return 4; + } } } diff --git a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs index f50496068f91d..9ac8a57318ec9 100644 --- a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs +++ b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs @@ -1719,7 +1719,6 @@ public void WriteMetadataAndIL(PdbWriter? nativePdbWriterOpt, Stream metadataStr Debug.Assert(typeSystemRowCounts[(int)TableIndex.EncMap] == 0); PopulateEncTables(typeSystemRowCounts); - Debug.Assert(mappedFieldDataBuilder == null); Debug.Assert(managedResourceDataBuilder == null); Debug.Assert(mvidFixup.IsDefault); Debug.Assert(mvidStringFixup.IsDefault); @@ -1742,9 +1741,13 @@ public void WriteMetadataAndIL(PdbWriter? nativePdbWriterOpt, Stream metadataStr try { ilBuilder.WriteContentTo(ilStream); + + // in EnC delta FieldRVA data are appended to the IL stream: + mappedFieldDataBuilder?.WriteContentTo(ilStream); + metadataBuilder.WriteContentTo(metadataStream); } - catch (Exception e) when (!(e is OperationCanceledException)) + catch (Exception e) when (e is not OperationCanceledException) { throw new PeWritingException(e); } @@ -1844,7 +1847,10 @@ public void BuildMetadataAndIL( _dynamicAnalysisDataWriterOpt.SerializeMetadataTables(dynamicAnalysisData); } - PopulateTypeSystemTables(methodBodyOffsets, out mappedFieldDataBuilder, out managedResourceDataBuilder, dynamicAnalysisData, out mvidFixup); + // in EnC delta the FieldRVA data is stored to IL stream following all the method bodies: + int mappedFieldDataStartOffset = IsFullMetadata ? 0 : ilBuilder.Count; + + PopulateTypeSystemTables(methodBodyOffsets, mappedFieldDataStartOffset, out mappedFieldDataBuilder, out managedResourceDataBuilder, dynamicAnalysisData, out mvidFixup); dynamicAnalysisData?.Free(); } #nullable disable @@ -1907,7 +1913,7 @@ private ImmutableArray GetSortedGenericParameters() } #nullable enable - private void PopulateTypeSystemTables(int[] methodBodyOffsets, out PooledBlobBuilder? mappedFieldDataWriter, out PooledBlobBuilder? resourceWriter, BlobBuilder? dynamicAnalysisData, out Blob mvidFixup) + private void PopulateTypeSystemTables(int[] methodBodyOffsets, int mappedFieldDataStartOffset, out PooledBlobBuilder? mappedFieldDataWriter, out PooledBlobBuilder? resourceWriter, BlobBuilder? dynamicAnalysisData, out Blob mvidFixup) { var sortedGenericParameters = GetSortedGenericParameters(); @@ -1921,7 +1927,7 @@ private void PopulateTypeSystemTables(int[] methodBodyOffsets, out PooledBlobBui this.PopulateExportedTypeTableRows(); this.PopulateFieldLayoutTableRows(); this.PopulateFieldMarshalTableRows(); - this.PopulateFieldRvaTableRows(out mappedFieldDataWriter); + this.PopulateFieldRvaTableRows(mappedFieldDataStartOffset, out mappedFieldDataWriter); this.PopulateFieldTableRows(); this.PopulateFileTableRows(); this.PopulateGenericParameters(sortedGenericParameters); @@ -2329,9 +2335,9 @@ private void PopulateFieldMarshalTableRows() } #nullable enable - private void PopulateFieldRvaTableRows(out PooledBlobBuilder? mappedFieldDataWriter) + private void PopulateFieldRvaTableRows(int mappedFieldDataStartOffset, out PooledBlobBuilder? mappedFieldDataBuilder) { - mappedFieldDataWriter = null; + mappedFieldDataBuilder = null; foreach (IFieldDefinition fieldDef in this.GetFieldDefs()) { @@ -2340,19 +2346,26 @@ private void PopulateFieldRvaTableRows(out PooledBlobBuilder? mappedFieldDataWri continue; } - mappedFieldDataWriter ??= PooledBlobBuilder.GetInstance(); + if (mappedFieldDataBuilder == null) + { + mappedFieldDataBuilder = PooledBlobBuilder.GetInstance(); + + // insert alignment bytes as needed: + var alignedStartOffset = BitArithmeticUtilities.Align(mappedFieldDataStartOffset, ManagedPEBuilder.MappedFieldDataAlignment); + mappedFieldDataBuilder.WriteBytes(0, alignedStartOffset - mappedFieldDataStartOffset); + } // The compiler always aligns each RVA data field to an 8-byte boundary; this accommodates the alignment // needs for all primitive types, regardless of which type is actually being used, at the expense of // potentially wasting up to 7 bytes per field if the alignment needs are less. In the future, this // potentially could be tightened to align each field only as much as is actually required by that // field, saving a few bytes per field. - int offset = mappedFieldDataWriter.Count; + int offset = mappedFieldDataStartOffset + mappedFieldDataBuilder.Count; Debug.Assert(offset % ManagedPEBuilder.MappedFieldDataAlignment == 0, "Expected last write to end at alignment boundary"); Debug.Assert(ManagedPEBuilder.MappedFieldDataAlignment == 8, "Expected alignment to be 8"); - mappedFieldDataWriter.WriteBytes(fieldDef.MappedData); - mappedFieldDataWriter.Align(ManagedPEBuilder.MappedFieldDataAlignment); + mappedFieldDataBuilder.WriteBytes(fieldDef.MappedData); + mappedFieldDataBuilder.Align(ManagedPEBuilder.MappedFieldDataAlignment); metadata.AddFieldRelativeVirtualAddress( field: GetFieldDefinitionHandle(fieldDef), diff --git a/src/Compilers/Core/Portable/PEWriter/MethodDefinitionBase.cs b/src/Compilers/Core/Portable/PEWriter/MethodDefinitionBase.cs index 712124d888ce8..3e5e4814c3b5b 100644 --- a/src/Compilers/Core/Portable/PEWriter/MethodDefinitionBase.cs +++ b/src/Compilers/Core/Portable/PEWriter/MethodDefinitionBase.cs @@ -149,13 +149,13 @@ public MethodDefinitionBase(ITypeDefinition containingTypeDefinition, ushort max public DebugId MethodId => default; - public ImmutableArray StateMachineHoistedLocalScopes => ImmutableArray.Empty; + public ImmutableArray StateMachineHoistedLocalScopes => default; public string StateMachineTypeName => null; - public ImmutableArray StateMachineHoistedLocalSlots => ImmutableArray.Empty; + public ImmutableArray StateMachineHoistedLocalSlots => default; - public ImmutableArray StateMachineAwaiterSlots => ImmutableArray.Empty; + public ImmutableArray StateMachineAwaiterSlots => default; public ImmutableArray ClosureDebugInfo => ImmutableArray.Empty; diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index a093220786c15..d93281dfa3460 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -1,13 +1,17 @@ +Microsoft.CodeAnalysis.Compilation.EmitDifference(Microsoft.CodeAnalysis.Emit.EmitBaseline! baseline, System.Collections.Generic.IEnumerable! edits, System.Func! isAddedSymbol, System.IO.Stream! metadataStream, System.IO.Stream! ilStream, System.IO.Stream! pdbStream, Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.Emit.EmitDifferenceResult! +Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions +Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions.EmitDifferenceOptions() -> void +Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions.EmitFieldRva.get -> bool +Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions.EmitFieldRva.init -> void +static readonly Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions.Default -> Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions Microsoft.CodeAnalysis.IEventSymbol.IsPartialDefinition.get -> bool Microsoft.CodeAnalysis.IEventSymbol.PartialDefinitionPart.get -> Microsoft.CodeAnalysis.IEventSymbol? Microsoft.CodeAnalysis.IEventSymbol.PartialImplementationPart.get -> Microsoft.CodeAnalysis.IEventSymbol? Microsoft.CodeAnalysis.IncrementalGeneratorPostInitializationContext.AddEmbeddedAttributeDefinition() -> void override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.ToString() -> string! - Microsoft.CodeAnalysis.ITypeSymbol.IsExtension.get -> bool Microsoft.CodeAnalysis.TypeKind.Extension = 14 -> Microsoft.CodeAnalysis.TypeKind Microsoft.CodeAnalysis.ITypeSymbol.ExtensionParameter.get -> Microsoft.CodeAnalysis.IParameterSymbol? - const Microsoft.CodeAnalysis.WellKnownMemberNames.AdditionAssignmentOperatorName = "op_AdditionAssignment" -> string! const Microsoft.CodeAnalysis.WellKnownMemberNames.BitwiseAndAssignmentOperatorName = "op_BitwiseAndAssignment" -> string! const Microsoft.CodeAnalysis.WellKnownMemberNames.BitwiseOrAssignmentOperatorName = "op_BitwiseOrAssignment" -> string! @@ -26,4 +30,4 @@ const Microsoft.CodeAnalysis.WellKnownMemberNames.UnsignedRightShiftAssignmentOp const Microsoft.CodeAnalysis.WellKnownMemberNames.CheckedDecrementAssignmentOperatorName = "op_CheckedDecrementAssignment" -> string! const Microsoft.CodeAnalysis.WellKnownMemberNames.CheckedIncrementAssignmentOperatorName = "op_CheckedIncrementAssignment" -> string! const Microsoft.CodeAnalysis.WellKnownMemberNames.DecrementAssignmentOperatorName = "op_DecrementAssignment" -> string! -const Microsoft.CodeAnalysis.WellKnownMemberNames.IncrementAssignmentOperatorName = "op_IncrementAssignment" -> string! \ No newline at end of file +const Microsoft.CodeAnalysis.WellKnownMemberNames.IncrementAssignmentOperatorName = "op_IncrementAssignment" -> string! diff --git a/src/Compilers/Test/Core/Compilation/CompilationDifference.cs b/src/Compilers/Test/Core/Compilation/CompilationDifference.cs index 7e2c84c4e028c..164703d1fc3b4 100644 --- a/src/Compilers/Test/Core/Compilation/CompilationDifference.cs +++ b/src/Compilers/Test/Core/Compilation/CompilationDifference.cs @@ -64,7 +64,8 @@ public void VerifyIL( [CallerLineNumber] int callerLine = 0, [CallerFilePath] string callerPath = null) { - string actualIL = ILDelta.GetMethodIL(); + using var readerProvider = MetadataReaderProvider.FromMetadataImage(MetadataDelta); + string actualIL = ILValidation.DumpEncDeltaMethodBodies(ILDelta, [readerProvider.GetMetadataReader()]); AssertEx.AssertEqualToleratingWhitespaceDifferences(expectedIL, actualIL, escapeQuotes: false, expectedValueSourcePath: callerPath, expectedValueSourceLine: callerLine); } diff --git a/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs b/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs index e2fdfbcc60d5b..32f881abf5f02 100644 --- a/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs +++ b/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs @@ -142,6 +142,7 @@ internal static CompilationDifference EmitDifference( EmitBaseline baseline, ImmutableArray edits, IEnumerable allAddedSymbols = null, + EmitDifferenceOptions? options = null, CompilationTestData testData = null) { testData ??= new CompilationTestData(); @@ -158,6 +159,7 @@ internal static CompilationDifference EmitDifference( mdStream, ilStream, pdbStream, + options ?? EmitDifferenceOptions.Default, testData, CancellationToken.None); diff --git a/src/Compilers/Test/Core/Metadata/ILBuilderVisualizer.cs b/src/Compilers/Test/Core/Metadata/ILBuilderVisualizer.cs index b002e0c839cac..6c4b3b99c5af1 100644 --- a/src/Compilers/Test/Core/Metadata/ILBuilderVisualizer.cs +++ b/src/Compilers/Test/Core/Metadata/ILBuilderVisualizer.cs @@ -5,29 +5,29 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Reflection.Emit; using System.Reflection.Metadata; using System.Text; -using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeGen; +using Microsoft.CodeAnalysis.Emit; +using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Symbols; using Microsoft.Metadata.Tools; using Roslyn.Utilities; using Cci = Microsoft.Cci; -using Microsoft.CodeAnalysis.Symbols; -using System.Diagnostics; -using System.Reflection.Metadata.Ecma335; namespace Roslyn.Test.Utilities { internal sealed class ILBuilderVisualizer : ILVisualizer { - private readonly ITokenDeferral _tokenDeferral; + private readonly CommonPEModuleBuilder _module; private readonly SymbolDisplayFormat _symbolDisplayFormat; - public ILBuilderVisualizer(ITokenDeferral tokenDeferral, SymbolDisplayFormat? symbolDisplayFormat = null) + public ILBuilderVisualizer(CommonPEModuleBuilder module, SymbolDisplayFormat? symbolDisplayFormat = null) { - _tokenDeferral = tokenDeferral; + _module = module; _symbolDisplayFormat = symbolDisplayFormat ?? SymbolDisplayFormat.ILVisualizationFormat; } @@ -39,7 +39,7 @@ public override string VisualizeUserString(uint token) return "##MVID##"; } - return "\"" + _tokenDeferral.GetStringFromToken(token) + "\""; + return "\"" + _module.GetStringFromToken(token) + "\""; } public override string VisualizeSymbol(uint token, OperandType operandType) @@ -58,7 +58,7 @@ public override string VisualizeSymbol(uint token, OperandType operandType) token &= 0xffffff; } - object reference = _tokenDeferral.GetReferenceFromToken(token); + object reference = _module.GetReferenceFromToken(token); ISymbol? symbol = ((reference as ISymbolInternal) ?? (reference as Cci.IReference)?.GetInternalSymbol())?.GetISymbol(); return string.Format("\"{0}\"", symbol == null ? (object)reference : symbol.ToDisplayString(_symbolDisplayFormat)); } @@ -140,6 +140,8 @@ internal static string ILBuilderToString( IReadOnlyDictionary? markers = null, SymbolDisplayFormat? ilFormat = null) { + Debug.Assert(builder.LocalSlotManager != null); + var sb = new StringBuilder(); var ilStream = builder.RealizedIL; @@ -178,6 +180,8 @@ internal static string LocalSignatureToString( ILBuilder builder, Func? mapLocal = null) { + Debug.Assert(builder.LocalSlotManager != null); + var sb = new StringBuilder(); if (mapLocal == null) diff --git a/src/Compilers/Test/Core/Metadata/ILValidation.cs b/src/Compilers/Test/Core/Metadata/ILValidation.cs index 0503ba220aac3..0d54449bcf116 100644 --- a/src/Compilers/Test/Core/Metadata/ILValidation.cs +++ b/src/Compilers/Test/Core/Metadata/ILValidation.cs @@ -7,10 +7,12 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; using System.Security.Cryptography; using System.Text; @@ -263,50 +265,98 @@ private static IEnumerable GetContentToSign( }); } - public static unsafe string GetMethodIL(this ImmutableArray ilArray) + public static unsafe string DumpEncDeltaMethodBodies(ImmutableArray il, ImmutableArray readers) { + var reader = readers[^1]; + + var rvasAndNames = from handle in reader.MethodDefinitions + let method = reader.GetMethodDefinition(handle) + orderby method.RelativeVirtualAddress + group method.Name by method.RelativeVirtualAddress into g + // Legacy test support: name can only be resolved when readers for all generations are given. + select (g.Key, readers.Length > 1 ? string.Join(", ", g.Select(readers.GetString)) : null); + var result = new StringBuilder(); - fixed (byte* ilPtr = ilArray.ToArray()) + + fixed (byte* ilPtr = il.ToArray()) { - int offset = 0; - while (true) - { - // skip padding: - while (offset < ilArray.Length && ilArray[offset] == 0) - { - offset++; - } + var bodyReader = new BlobReader(ilPtr, il.Length); - if (offset == ilArray.Length) + foreach (var (rva, name) in rvasAndNames) + { + if (name != null) { - break; + result.AppendLine(name); } - var reader = new BlobReader(ilPtr + offset, ilArray.Length - offset); - var methodIL = MethodBodyBlock.Create(reader); + bodyReader.Offset = rva; - if (methodIL == null) + MethodBodyBlock body; + try { - result.AppendFormat("", ilArray[offset], offset); - offset++; + body = MethodBodyBlock.Create(bodyReader); } - else + catch (BadImageFormatException) { - ILVisualizer.Default.DumpMethod( - result, - methodIL.MaxStack, - methodIL.GetILContent(), - ImmutableArray.Create(), - ImmutableArray.Create()); - - offset += methodIL.Size; + result.AppendFormat("", il[rva], rva); + continue; } + + ILVisualizer.Default.DumpMethod( + result, + body.MaxStack, + body.GetILContent(), + locals: [], + exceptionHandlers: []); } } return result.ToString(); } + public static unsafe string DumpEncDeltaFieldData(ImmutableArray il, ImmutableArray readers) + { + var reader = readers[^1]; + var aggregator = new MetadataAggregator(readers[0], readers[1..]); + + var fieldRvaTablePtr = reader.MetadataPointer + reader.GetTableMetadataOffset(TableIndex.FieldRva); + var rowCount = reader.GetTableRowCount(TableIndex.FieldRva); + var rowSize = reader.GetTableRowSize(TableIndex.FieldRva); + var tableReader = new BlobReader(fieldRvaTablePtr, rowCount * rowSize); + + var rvasAndNames = new List<(int rva, string name)>(); + for (var i = 0; i < rowCount; i++) + { + var rva = tableReader.ReadInt32(); + + // RowIds are 4 bytes in EnC deltas + var fieldRowId = tableReader.ReadInt32(); + + if (rva > 0) + { + var fieldHandle = MetadataTokens.FieldDefinitionHandle(fieldRowId); + var genFieldHandle = (FieldDefinitionHandle)aggregator.GetGenerationHandle(fieldHandle, out var fieldGen); + var fieldDef = readers[fieldGen].GetFieldDefinition(genFieldHandle); + var genNameHandle = (StringHandle)aggregator.GetGenerationHandle(fieldDef.Name, out var nameGen); + var fieldName = readers[nameGen].GetString(genNameHandle); + + rvasAndNames.Add((rva, fieldName)); + } + } + + var result = new StringBuilder(); + + for (var i = 0; i < rvasAndNames.Count; i++) + { + var (startRva, name) = rvasAndNames[i]; + var endRva = i + 1 < rvasAndNames.Count ? rvasAndNames[i + 1].rva : il.Length; + + result.AppendLine($"{name}: {BitConverter.ToString(il[startRva..endRva].ToArray())}"); + } + + return result.ToString(); + } + public static unsafe MethodBodyBlock GetMethodBodyBlock(this ImmutableArray ilArray) { fixed (byte* ilPtr = ilArray.AsSpan()) diff --git a/src/Compilers/Test/Core/Mocks/TestMessageProvider.cs b/src/Compilers/Test/Core/Mocks/TestMessageProvider.cs index b3fa3ea6172e3..98fa2e6c6df14 100644 --- a/src/Compilers/Test/Core/Mocks/TestMessageProvider.cs +++ b/src/Compilers/Test/Core/Mocks/TestMessageProvider.cs @@ -400,6 +400,14 @@ public override int ERR_TooManyUserStrings } } + public override int ERR_TooManyUserStrings_RestartRequired + { + get + { + throw new NotImplementedException(); + } + } + public override int ERR_PeWritingFailure { get diff --git a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs index 7cff6341780e6..0611918d426a0 100644 --- a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs +++ b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs @@ -2114,6 +2114,8 @@ internal static unsafe string VisualizeRealIL(PEModuleSymbol peModule, Compilati return ImmutableArray.Create(); } + Debug.Assert(builder.LocalSlotManager != null); + var result = new ILVisualizer.LocalInfo[localInfos.Length]; for (int i = 0; i < result.Length; i++) { diff --git a/src/Compilers/VisualBasic/Portable/CodeGen/CodeGenerator.vb b/src/Compilers/VisualBasic/Portable/CodeGen/CodeGenerator.vb index 479e808325b56..75e96864cf563 100644 --- a/src/Compilers/VisualBasic/Portable/CodeGen/CodeGenerator.vb +++ b/src/Compilers/VisualBasic/Portable/CodeGen/CodeGenerator.vb @@ -190,16 +190,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen End Function Private Sub EmitSymbolToken(symbol As FieldSymbol, syntaxNode As SyntaxNode) - _builder.EmitToken(_module.Translate(symbol, syntaxNode, _diagnostics), syntaxNode, _diagnostics) + _builder.EmitToken(_module.Translate(symbol, syntaxNode, _diagnostics), syntaxNode) End Sub Private Sub EmitSymbolToken(symbol As MethodSymbol, syntaxNode As SyntaxNode, Optional encodeAsRawDefinitionToken As Boolean = False) Dim methodRef = _module.Translate(symbol, syntaxNode, _diagnostics, needDeclaration:=encodeAsRawDefinitionToken) - _builder.EmitToken(methodRef, syntaxNode, _diagnostics, If(encodeAsRawDefinitionToken, Cci.MetadataWriter.RawTokenEncoding.RowId, Cci.MetadataWriter.RawTokenEncoding.None)) + _builder.EmitToken(methodRef, syntaxNode, If(encodeAsRawDefinitionToken, Cci.MetadataWriter.RawTokenEncoding.RowId, Cci.MetadataWriter.RawTokenEncoding.None)) End Sub Private Sub EmitSymbolToken(symbol As TypeSymbol, syntaxNode As SyntaxNode) - _builder.EmitToken(_module.Translate(symbol, syntaxNode, _diagnostics), syntaxNode, _diagnostics) + _builder.EmitToken(_module.Translate(symbol, syntaxNode, _diagnostics), syntaxNode) End Sub Private Sub EmitSequencePointExpression(node As BoundSequencePointExpression, used As Boolean) diff --git a/src/Compilers/VisualBasic/Portable/CodeGen/EmitAddress.vb b/src/Compilers/VisualBasic/Portable/CodeGen/EmitAddress.vb index 07a97a9f19cbf..dc61bf6aa465f 100644 --- a/src/Compilers/VisualBasic/Portable/CodeGen/EmitAddress.vb +++ b/src/Compilers/VisualBasic/Portable/CodeGen/EmitAddress.vb @@ -418,7 +418,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen _builder.EmitOpCode(ILOpCode.Ldelema) EmitSymbolToken(elementType, arrayAccess.Syntax) Else - _builder.EmitArrayElementAddress(_module.Translate(DirectCast(arrayAccess.Expression.Type, ArrayTypeSymbol)), arrayAccess.Syntax, _diagnostics) + _builder.EmitArrayElementAddress(_module.Translate(DirectCast(arrayAccess.Expression.Type, ArrayTypeSymbol)), arrayAccess.Syntax) End If End Sub diff --git a/src/Compilers/VisualBasic/Portable/CodeGen/EmitArrayInitializer.vb b/src/Compilers/VisualBasic/Portable/CodeGen/EmitArrayInitializer.vb index 2b36682d656a1..51cc53e794be2 100644 --- a/src/Compilers/VisualBasic/Portable/CodeGen/EmitArrayInitializer.vb +++ b/src/Compilers/VisualBasic/Portable/CodeGen/EmitArrayInitializer.vb @@ -41,7 +41,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen If initializationStyle = ArrayInitializerStyle.Element Then Me.EmitElementInitializers(arrayType, initExprs, True) Else - _builder.EmitArrayBlockInitializer(Me.GetRawData(initExprs), inits.Syntax, _diagnostics) + _builder.EmitArrayBlockInitializer(Me.GetRawData(initExprs), inits.Syntax) If initializationStyle = ArrayInitializerStyle.Mixed Then EmitElementInitializers(arrayType, initExprs, False) @@ -188,9 +188,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen End Function Private Function ShouldEmitBlockInitializer(elementType As TypeSymbol, inits As ImmutableArray(Of BoundExpression)) As ArrayInitializerStyle - If _module.IsEncDelta Then - ' Avoid using FieldRva table. Can be allowed if tested on all supported runtimes. - ' Consider removing: https://github.com/dotnet/roslyn/issues/69480 + If Not _module.FieldRvaSupported Then + ' Avoid using FieldRva table if the runtime does not support it. Return ArrayInitializerStyle.Element End If diff --git a/src/Compilers/VisualBasic/Portable/CodeGen/EmitConversion.vb b/src/Compilers/VisualBasic/Portable/CodeGen/EmitConversion.vb index 371a4af5b01e7..3c71c1f6f3d13 100644 --- a/src/Compilers/VisualBasic/Portable/CodeGen/EmitConversion.vb +++ b/src/Compilers/VisualBasic/Portable/CodeGen/EmitConversion.vb @@ -75,7 +75,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen ' Handle conversions to Boolean If underlyingTo = PrimitiveTypeCode.Boolean Then ' Emit Zero - _builder.EmitConstantValue(ConstantValue.Default(underlyingFrom.GetConstantValueTypeDiscriminator())) + _builder.EmitConstantValue(ConstantValue.Default(underlyingFrom.GetConstantValueTypeDiscriminator()), conversion.Syntax) ' using cgt.un is optimal, but doesn't work in the case of floating point values If underlyingFrom.IsFloatingPoint() Then diff --git a/src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb b/src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb index 297f77c7ff3cb..6bfe58eaac5e1 100644 --- a/src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb +++ b/src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb @@ -649,7 +649,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen End If End Select Else - _builder.EmitArrayElementLoad(_module.Translate(DirectCast(arrayAccess.Expression.Type, ArrayTypeSymbol)), arrayAccess.Expression.Syntax, _diagnostics) + _builder.EmitArrayElementLoad(_module.Translate(DirectCast(arrayAccess.Expression.Type, ArrayTypeSymbol)), arrayAccess.Expression.Syntax) End If EmitPopIfUnused(used) @@ -1630,7 +1630,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen _builder.EmitOpCode(ILOpCode.Newarr) EmitSymbolToken(arrayType.ElementType, expression.Syntax) Else - _builder.EmitArrayCreation(_module.Translate(arrayType), expression.Syntax, _diagnostics) + _builder.EmitArrayCreation(_module.Translate(arrayType), expression.Syntax) End If If expression.InitializerOpt IsNot Nothing Then @@ -1734,7 +1734,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen If ((type IsNot Nothing) AndAlso (type.TypeKind = TypeKind.TypeParameter) AndAlso constantValue.IsNull) Then EmitInitObj(type, used, syntaxNode) Else - _builder.EmitConstantValue(constantValue) + _builder.EmitConstantValue(constantValue, syntaxNode) End If End If End Sub @@ -2107,7 +2107,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen If arrayType.IsSZArray Then EmitVectorElementStore(arrayType, syntaxNode) Else - _builder.EmitArrayElementStore(_module.Translate(arrayType), syntaxNode, _diagnostics) + _builder.EmitArrayElementStore(_module.Translate(arrayType), syntaxNode) End If End Sub @@ -2355,7 +2355,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen End Sub Private Sub EmitModuleVersionIdToken(node As BoundModuleVersionId) - _builder.EmitToken(_module.GetModuleVersionId(_module.Translate(node.Type, node.Syntax, _diagnostics), node.Syntax, _diagnostics), node.Syntax, _diagnostics) + _builder.EmitToken(_module.GetModuleVersionId(_module.Translate(node.Type, node.Syntax, _diagnostics), node.Syntax, _diagnostics), node.Syntax) End Sub Private Sub EmitModuleVersionIdStringLoad(node As BoundModuleVersionIdString) @@ -2374,7 +2374,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen End Sub Private Sub EmitInstrumentationPayloadRootToken(node As BoundInstrumentationPayloadRoot) - _builder.EmitToken(_module.GetInstrumentationPayloadRoot(node.AnalysisKind, _module.Translate(node.Type, node.Syntax, _diagnostics), node.Syntax, _diagnostics), node.Syntax, _diagnostics) + _builder.EmitToken(_module.GetInstrumentationPayloadRoot(node.AnalysisKind, _module.Translate(node.Type, node.Syntax, _diagnostics), node.Syntax, _diagnostics), node.Syntax) End Sub Private Sub EmitSourceDocumentIndex(node As BoundSourceDocumentIndex) diff --git a/src/Compilers/VisualBasic/Portable/CodeGen/EmitOperators.vb b/src/Compilers/VisualBasic/Portable/CodeGen/EmitOperators.vb index 39fcbc0699b31..b5b009cfa4c76 100644 --- a/src/Compilers/VisualBasic/Portable/CodeGen/EmitOperators.vb +++ b/src/Compilers/VisualBasic/Portable/CodeGen/EmitOperators.vb @@ -327,7 +327,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen Dim shiftMax = GetShiftSizeMask(expression.Left.Type) Dim shiftConst = expression.Right.ConstantValueOpt If shiftConst Is Nothing OrElse shiftConst.UInt32Value > shiftMax Then - _builder.EmitConstantValue(ConstantValue.Create(shiftMax)) + _builder.EmitConstantValue(ConstantValue.Create(shiftMax), expression.Right.Syntax) _builder.EmitOpCode(ILOpCode.And) End If @@ -342,7 +342,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen Dim shiftMax = GetShiftSizeMask(expression.Left.Type) Dim shiftConst = expression.Right.ConstantValueOpt If shiftConst Is Nothing OrElse shiftConst.UInt32Value > shiftMax Then - _builder.EmitConstantValue(ConstantValue.Create(shiftMax)) + _builder.EmitConstantValue(ConstantValue.Create(shiftMax), expression.Right.Syntax) _builder.EmitOpCode(ILOpCode.And) End If @@ -579,7 +579,7 @@ BinaryOperatorKindEqual: EmitBox(comparandType, comparand.Syntax) End If - _builder.EmitConstantValue(nullOrZero) + _builder.EmitConstantValue(nullOrZero, comparand.Syntax) _builder.EmitOpCode(ILOpCode.Cgt_un) End Sub @@ -591,7 +591,7 @@ BinaryOperatorKindEqual: EmitBox(comparandType, comparand.Syntax) End If - _builder.EmitConstantValue(nullOrZero) + _builder.EmitConstantValue(nullOrZero, comparand.Syntax) _builder.EmitOpCode(ILOpCode.Ceq) End Sub diff --git a/src/Compilers/VisualBasic/Portable/CodeGen/EmitStatement.vb b/src/Compilers/VisualBasic/Portable/CodeGen/EmitStatement.vb index a923f82f0ac79..d0991f50819a9 100644 --- a/src/Compilers/VisualBasic/Portable/CodeGen/EmitStatement.vb +++ b/src/Compilers/VisualBasic/Portable/CodeGen/EmitStatement.vb @@ -227,7 +227,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen 'Determine if the exception object is or inherits from System.Exception _builder.EmitOpCode(ILOpCode.Isinst) - _builder.EmitToken(exceptionType, catchBlock.Syntax, _diagnostics) + _builder.EmitToken(exceptionType, catchBlock.Syntax) _builder.EmitOpCode(ILOpCode.Ldnull) _builder.EmitOpCode(ILOpCode.Cgt_un) @@ -251,7 +251,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen _builder.MarkFilterConditionEnd() _builder.EmitOpCode(ILOpCode.Castclass) - _builder.EmitToken(exceptionType, catchBlock.Syntax, _diagnostics) + _builder.EmitToken(exceptionType, catchBlock.Syntax) If ShouldNoteProjectErrors() Then EmitSetProjectError(catchBlock.Syntax, catchBlock.ErrorLineNumberOpt) @@ -278,7 +278,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen typeCheckFailedLabel = New Object _builder.EmitOpCode(ILOpCode.Isinst) - _builder.EmitToken(exceptionType, catchBlock.Syntax, _diagnostics) + _builder.EmitToken(exceptionType, catchBlock.Syntax) _builder.EmitOpCode(ILOpCode.Dup) _builder.EmitBranch(ILOpCode.Brtrue, typeCheckPassedLabel) _builder.EmitOpCode(ILOpCode.Pop) @@ -1048,32 +1048,33 @@ OtherExpressions: Else Dim exprType = selectExpression.Type + Dim syntax As SyntaxNode = selectExpression.Syntax Dim temp As LocalDefinition = Nothing If exprType.SpecialType <> SpecialType.System_String Then If selectExpression.Kind = BoundKind.Local AndAlso Not DirectCast(selectExpression, BoundLocal).LocalSymbol.IsByRef Then - _builder.EmitIntegerSwitchJumpTable(caseLabels, fallThroughLabel, GetLocal(DirectCast(selectExpression, BoundLocal)), keyTypeCode:=exprType.GetEnumUnderlyingTypeOrSelf.PrimitiveTypeCode) + _builder.EmitIntegerSwitchJumpTable(caseLabels, fallThroughLabel, GetLocal(DirectCast(selectExpression, BoundLocal)), keyTypeCode:=exprType.GetEnumUnderlyingTypeOrSelf.PrimitiveTypeCode, syntax) ElseIf selectExpression.Kind = BoundKind.Parameter AndAlso Not DirectCast(selectExpression, BoundParameter).ParameterSymbol.IsByRef Then - _builder.EmitIntegerSwitchJumpTable(caseLabels, fallThroughLabel, ParameterSlot(DirectCast(selectExpression, BoundParameter)), keyTypeCode:=exprType.GetEnumUnderlyingTypeOrSelf.PrimitiveTypeCode) + _builder.EmitIntegerSwitchJumpTable(caseLabels, fallThroughLabel, ParameterSlot(DirectCast(selectExpression, BoundParameter)), keyTypeCode:=exprType.GetEnumUnderlyingTypeOrSelf.PrimitiveTypeCode, syntax) Else EmitExpression(selectExpression, True) - temp = AllocateTemp(exprType, selectExpression.Syntax) + temp = AllocateTemp(exprType, syntax) _builder.EmitLocalStore(temp) - _builder.EmitIntegerSwitchJumpTable(caseLabels, fallThroughLabel, temp, keyTypeCode:=exprType.GetEnumUnderlyingTypeOrSelf.PrimitiveTypeCode) + _builder.EmitIntegerSwitchJumpTable(caseLabels, fallThroughLabel, temp, keyTypeCode:=exprType.GetEnumUnderlyingTypeOrSelf.PrimitiveTypeCode, syntax) End If Else If selectExpression.Kind = BoundKind.Local AndAlso Not DirectCast(selectExpression, BoundLocal).LocalSymbol.IsByRef Then - EmitStringSwitchJumpTable(caseLabels, fallThroughLabel, GetLocal(DirectCast(selectExpression, BoundLocal)), selectExpression.Syntax) + EmitStringSwitchJumpTable(caseLabels, fallThroughLabel, GetLocal(DirectCast(selectExpression, BoundLocal)), syntax) Else EmitExpression(selectExpression, True) - temp = AllocateTemp(exprType, selectExpression.Syntax) + temp = AllocateTemp(exprType, syntax) _builder.EmitLocalStore(temp) - EmitStringSwitchJumpTable(caseLabels, fallThroughLabel, temp, selectExpression.Syntax) + EmitStringSwitchJumpTable(caseLabels, fallThroughLabel, temp, syntax) End If End If @@ -1099,7 +1100,7 @@ OtherExpressions: _builder.EmitLocalLoad(key) _builder.EmitOpCode(ILOpCode.[Call], stackAdjustment:=0) - _builder.EmitToken(stringHashMethodRef, syntaxNode, _diagnostics) + _builder.EmitToken(stringHashMethodRef, syntaxNode) Dim UInt32Type = DirectCast(_module.GetSpecialType(SpecialType.System_UInt32, syntaxNode, _diagnostics).GetInternalSymbol(), TypeSymbol) keyHash = AllocateTemp(UInt32Type, syntaxNode) @@ -1123,6 +1124,7 @@ OtherExpressions: End Sub _builder.EmitStringSwitchJumpTable( + syntaxNode, caseLabels, fallThroughLabel, key, @@ -1171,10 +1173,10 @@ OtherExpressions: ' NOTE: We generate string switch table only for Option Compare Binary, i.e. TextCompare = False _builder.EmitLoad(key) - _builder.EmitConstantValue(stringConstant) - _builder.EmitConstantValue(ConstantValue.False) + _builder.EmitConstantValue(stringConstant, syntaxNode) + _builder.EmitConstantValue(ConstantValue.False, syntaxNode) _builder.EmitOpCode(ILOpCode.Call, stackAdjustment:=-2) - _builder.EmitToken(stringCompareMethodRef, syntaxNode, _diagnostics) + _builder.EmitToken(stringCompareMethodRef, syntaxNode) ' CompareString returns 0 if Left and Right strings are equal. ' Branch to targetLabel if CompareString returned 0. diff --git a/src/Compilers/VisualBasic/Portable/Compilation/MethodCompiler.vb b/src/Compilers/VisualBasic/Portable/Compilation/MethodCompiler.vb index f0ace4940ea73..6759c1b62a613 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/MethodCompiler.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/MethodCompiler.vb @@ -269,6 +269,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic compiler.ProcessEmbeddedMethods() End If + ' Deleted definitions must be emitted before PrivateImplementationDetails are frozen since + ' it may add new members to it. All changes to PrivateImplementationDetails are additions, + ' so we don't need to create deleted method defs for those. + moduleBeingBuiltOpt.CreateDeletedMethodDefinitions(diagnostics.DiagnosticBag) + ' all threads that were adding methods must be finished now, we can freeze the class: Dim privateImplClass = moduleBeingBuiltOpt.FreezePrivateImplementationDetails() If privateImplClass IsNot Nothing Then @@ -1611,7 +1616,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic optimizations = OptimizationLevel.Release End If - Dim builder As ILBuilder = New ILBuilder(moduleBuilder, localSlotManager, optimizations, areLocalsZeroed:=True) + Dim builder As ILBuilder = New ILBuilder(moduleBuilder, localSlotManager, diagnostics.DiagnosticBag, optimizations, areLocalsZeroed:=True) Try Debug.Assert(Not diagnostics.HasAnyErrors) diff --git a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb index 549049a430208..78216504415db 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb @@ -2603,6 +2603,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic metadataStream As Stream, ilStream As Stream, pdbStream As Stream, + options As EmitDifferenceOptions, testData As CompilationTestData, cancellationToken As CancellationToken) As EmitDifferenceResult @@ -2614,6 +2615,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic metadataStream, ilStream, pdbStream, + options, testData, cancellationToken) End Function diff --git a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/EmitHelpers.vb b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/EmitHelpers.vb index 11f3d1c93a873..c8447c764146e 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/EmitHelpers.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/EmitHelpers.vb @@ -25,6 +25,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit metadataStream As Stream, ilStream As Stream, pdbStream As Stream, + options As EmitDifferenceOptions, testData As CompilationTestData, cancellationToken As CancellationToken) As EmitDifferenceResult @@ -86,6 +87,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit compilation.SourceAssembly, changes, emitOpts, + options, compilation.Options.OutputKind, serializationProperties, manifestResources, @@ -118,7 +120,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit newBaseline = compilation.SerializeToDeltaStreams( moduleBeingBuilt, definitionMap, - changes, metadataStream, ilStream, pdbStream, diff --git a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/PEDeltaAssemblyBuilder.vb b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/PEDeltaAssemblyBuilder.vb index 955d149b98831..88ad55df98eed 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/PEDeltaAssemblyBuilder.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/PEDeltaAssemblyBuilder.vb @@ -25,6 +25,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit Private ReadOnly _changes As SymbolChanges Private ReadOnly _deepTranslator As VisualBasicSymbolMatcher.DeepTranslator Private ReadOnly _predefinedHotReloadExceptionConstructor As MethodSymbol + Private ReadOnly _options As EmitDifferenceOptions ''' ''' HotReloadException type. May be created even if not used. We might find out @@ -46,6 +47,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit Public Sub New(sourceAssembly As SourceAssemblySymbol, changes As VisualBasicSymbolChanges, emitOptions As EmitOptions, + options As EmitDifferenceOptions, outputKind As OutputKind, serializationProperties As ModulePropertiesForSerialization, manifestResources As IEnumerable(Of ResourceDescription), @@ -54,6 +56,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit MyBase.New(sourceAssembly, emitOptions, outputKind, serializationProperties, manifestResources, additionalTypes:=ImmutableArray(Of NamedTypeSymbol).Empty) _changes = changes + _options = options ' Workaround for https://github.com/dotnet/roslyn/issues/3192. ' When compiling state machine we stash types of awaiters and state-machine hoisted variables, @@ -92,6 +95,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit End Get End Property + Public Overrides ReadOnly Property FieldRvaSupported As Boolean + Get + Return _options.EmitFieldRva + End Get + End Property + Friend Shared Function GetOrCreateMetadataSymbols(initialBaseline As EmitBaseline, compilation As VisualBasicCompilation) As EmitBaseline.MetadataSymbols If initialBaseline.LazyMetadataSymbols IsNot Nothing Then Return initialBaseline.LazyMetadataSymbols @@ -251,7 +260,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit End Function Public Overrides Function GetTopLevelTypeDefinitions(context As EmitContext) As IEnumerable(Of Cci.INamespaceTypeDefinition) - Return GetTopLevelTypeDefinitionsCore(context) + Return GetTopLevelTypeDefinitionsExcludingNoPiaAndRootModule(context, includePrivateImplementationDetails:=True) End Function Public Overrides Function GetTopLevelSourceTypeDefinitions(context As EmitContext) As IEnumerable(Of Cci.INamespaceTypeDefinition) diff --git a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb index 6e53bb10ee2c2..be6752e8a4e07 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb @@ -45,7 +45,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit ' For simplicity, PID helpers and no-PIA embedded definitions are not reused across generations, so we don't map them here. ' Instead, new ones are regenerated as needed. - Debug.Assert(TypeOf definition Is PrivateImplementationDetails OrElse TypeOf definition Is Cci.IEmbeddedDefinition) + Debug.Assert(TypeOf definition Is PrivateImplementationDetails OrElse + TypeOf definition Is Cci.IEmbeddedDefinition OrElse + TypeOf definition Is MappedField OrElse + TypeOf definition Is ExplicitSizeStruct) Return Nothing End Function diff --git a/src/Compilers/VisualBasic/Portable/Emit/PEAssemblyBuilder.vb b/src/Compilers/VisualBasic/Portable/Emit/PEAssemblyBuilder.vb index d8c88417719c5..24e584bb216ae 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/PEAssemblyBuilder.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/PEAssemblyBuilder.vb @@ -33,7 +33,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit ''' Private ReadOnly _metadataName As String - Public Sub New(sourceAssembly As SourceAssemblySymbol, + Friend Sub New(sourceAssembly As SourceAssemblySymbol, emitOptions As EmitOptions, outputKind As OutputKind, serializationProperties As Cci.ModulePropertiesForSerialization, @@ -198,6 +198,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit End Get End Property + Public Overrides ReadOnly Property FieldRvaSupported As Boolean + Get + Return True + End Get + End Property + Public Overrides Function TryGetOrCreateSynthesizedHotReloadExceptionType() As INamedTypeSymbolInternal Return Nothing End Function diff --git a/src/Compilers/VisualBasic/Portable/Emit/PENetModuleBuilder.vb b/src/Compilers/VisualBasic/Portable/Emit/PENetModuleBuilder.vb index aad6b5c1be55e..e120c58453b79 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/PENetModuleBuilder.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/PENetModuleBuilder.vb @@ -45,6 +45,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit End Get End Property + Public Overrides ReadOnly Property FieldRvaSupported As Boolean + Get + Return True + End Get + End Property + Public Overrides Function TryGetOrCreateSynthesizedHotReloadExceptionType() As INamedTypeSymbolInternal Return Nothing End Function diff --git a/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb b/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb index ca8fcd8f48918..b6bb38d54e99f 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb @@ -1304,6 +1304,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ERRID.ERR_InvalidPathMap, ERRID.ERR_PublicSignNoKey, ERRID.ERR_TooManyUserStrings, + ERRID.ERR_TooManyUserStrings_RestartRequired, ERRID.ERR_PeWritingFailure, ERRID.ERR_OptionMustBeAbsolutePath, ERRID.ERR_DocFileGen, diff --git a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb index 2c425f89a3c2b..712f0a799f7d2 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb @@ -1787,8 +1787,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ERR_CannotApplyOverloadResolutionPriorityToMember = 37334 ERR_EmbeddedAttributeMustFollowPattern = 37335 + ERR_TooManyUserStrings_RestartRequired = 37336 - ERR_NextAvailable = 37336 + ERR_NextAvailable = 37337 '// WARNINGS BEGIN HERE WRN_UseOfObsoleteSymbol2 = 40000 diff --git a/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb b/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb index 0e573eaa217bd..153704ad8e975 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb @@ -558,6 +558,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property + Public Overrides ReadOnly Property ERR_TooManyUserStrings_RestartRequired As Integer + Get + Return ERRID.ERR_TooManyUserStrings_RestartRequired + End Get + End Property + Public Overrides ReadOnly Property ERR_PeWritingFailure As Integer Get Return ERRID.ERR_PeWritingFailure diff --git a/src/Compilers/VisualBasic/Portable/VBResources.resx b/src/Compilers/VisualBasic/Portable/VBResources.resx index c153096c40ad6..9545bc9cc30a9 100644 --- a/src/Compilers/VisualBasic/Portable/VBResources.resx +++ b/src/Compilers/VisualBasic/Portable/VBResources.resx @@ -5459,6 +5459,9 @@ Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string or XML literals. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + An error occurred while writing the output file: {0} diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf index cd99d16dde1e7..2d0bb2054efc1 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf @@ -132,6 +132,11 @@ {0} je definováno v sestavení {1}. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. Název typu {0} je vyhrazený pro použití kompilátorem. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf index f52b27726a1a1..956b1648d9288 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf @@ -132,6 +132,11 @@ "{0}" ist in Assembly "{1}" definiert. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. Der Typname "{0}" ist für die Verwendung durch den Compiler reserviert. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf index be3274c2999a9..8f3b3eda58e51 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf @@ -132,6 +132,11 @@ '{0}' se define en el ensamblado '{1}'. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. El nombre de tipo "{0}" está reservado para uso del compilador. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf index 4b05beae4f487..262a46314103f 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf @@ -132,6 +132,11 @@ '{0}' est défini dans l'assemblage '{1}'. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. L'utilisation du nom de type '{0}' est réservée au compilateur. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf index d7659c5a7ee3b..88e05af06655b 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf @@ -132,6 +132,11 @@ '{0}' è definito nell'assembly '{1}'. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. Il nome di tipo '{0}' è riservato al compilatore. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf index 440445efa7967..82a9a3cca5878 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf @@ -132,6 +132,11 @@ '{0}' はアセンブリ '{1}' で定義されています。 + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. 型名 '{0}' は、コンパイラによる使用のために予約されています。 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf index 3ccca121c0470..b9e34c1144700 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf @@ -132,6 +132,11 @@ '{0}'은(는) '{1}' 어셈블리에 정의되어 있습니다. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. 형식 이름 '{0}'은(는) 컴파일러에서 사용하도록 예약되어 있습니다. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf index ea736d6e939fe..194b290b41021 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf @@ -132,6 +132,11 @@ „{0}” jest zdefiniowany w zestawie „{1}”. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. Nazwa typu „{0}” jest zarezerwowana do użycia przez kompilator. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf index dd23654acf80a..6879c0913a3ac 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf @@ -132,6 +132,11 @@ '{0}' é definido no assembly '{1}'. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. O nome do tipo '{0}' está reservado para ser usado pelo compilador. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf index 075a143a0723a..2414dda323091 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf @@ -132,6 +132,11 @@ '{0}' определен в сборке '{1}'. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. Имя типа "{0}" зарезервировано для использования компилятором. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf index 6af7446cd9a65..11927a3b7d654 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf @@ -132,6 +132,11 @@ '{0}', '{1}' derlemesinde tanımlı. + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. '{0}' tür adı, derleyici tarafından kullanılmak üzere ayrılmıştır. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf index 7a5a5f73a5c49..e4c29d3e6e9a4 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf @@ -132,6 +132,11 @@ “{0}”在程序集“{1}”中定义。 + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. 类型名称“{0}”是保留给编译器使用的。 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf index 440e9c48e4924..40cae595794b4 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf @@ -132,6 +132,11 @@ '{0}' 於組件 '{1}' 中定義。 + + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + Combined length of user strings used by the program exceeds allowed limit. Adding a string or XML literal requires restarting the application. + + The type name '{0}' is reserved to be used by the compiler. 類型名稱 '{0}' 保留供編譯器使用。 diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.vb index b07005d502acb..a2735c380d293 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.vb @@ -2275,6 +2275,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__1-0", "_Lambda$__1-1", ".ctor", ".ctor", "_Lambda$__0#1") g.VerifyIL(" +F { // Code size 67 (0x43) .maxstack 2 @@ -2300,6 +2301,7 @@ End Class IL_0040: stloc.s V_5 IL_0042: ret } +_Lambda$__1-0 { // Code size 12 (0xc) .maxstack 8 @@ -2308,6 +2310,7 @@ End Class IL_0006: newobj 0x06000007 IL_000b: throw } +_Lambda$__1-1 { // Code size 9 (0x9) .maxstack 8 @@ -2317,6 +2320,7 @@ End Class IL_0007: nop IL_0008: ret } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -2328,6 +2332,7 @@ End Class IL_0009: stfld 0x04000004 IL_000e: ret } +.ctor { // Code size 7 (0x7) .maxstack 8 @@ -2335,6 +2340,7 @@ End Class IL_0001: call 0x0A00000C IL_0006: ret } +_Lambda$__0#1 { // Code size 14 (0xe) .maxstack 8 @@ -2392,6 +2398,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__1-0", "_Lambda$__1-1", ".ctor", ".ctor", "_Lambda$__1#1") g.VerifyIL(" +F { // Code size 66 (0x42) .maxstack 2 @@ -2417,6 +2424,7 @@ End Class IL_003f: stloc.s V_4 IL_0041: ret } +_Lambda$__1-0 { // Code size 9 (0x9) .maxstack 8 @@ -2426,6 +2434,7 @@ End Class IL_0007: nop IL_0008: ret } +_Lambda$__1-1 { // Code size 12 (0xc) .maxstack 8 @@ -2434,6 +2443,7 @@ End Class IL_0006: newobj 0x06000007 IL_000b: throw } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -2445,6 +2455,7 @@ End Class IL_0009: stfld 0x04000004 IL_000e: ret } +.ctor { // Code size 7 (0x7) .maxstack 8 @@ -2452,6 +2463,7 @@ End Class IL_0001: call 0x0A00000C IL_0006: ret } +_Lambda$__1#1 { // Code size 14 (0xe) .maxstack 8 @@ -2512,6 +2524,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__2-0", "_Lambda$__2-1", "_Lambda$__2-1#1", ".ctor") g.VerifyIL(" +F { // Code size 52 (0x34) .maxstack 2 @@ -2532,6 +2545,7 @@ End Class IL_0032: stloc.3 IL_0033: ret } +_Lambda$__2-0 { // Code size 9 (0x9) .maxstack 8 @@ -2541,6 +2555,7 @@ End Class IL_0007: nop IL_0008: ret } +_Lambda$__2-1 { // Code size 12 (0xc) .maxstack 8 @@ -2549,6 +2564,7 @@ End Class IL_0006: newobj 0x06000008 IL_000b: throw } +_Lambda$__2-1#1 { // Code size 14 (0xe) .maxstack 8 @@ -2559,6 +2575,7 @@ End Class IL_000c: nop IL_000d: ret } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -2617,6 +2634,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__0") g.VerifyIL(" +F { // Code size 30 (0x1e) .maxstack 2 @@ -2634,6 +2652,7 @@ End Class IL_001c: stloc.3 IL_001d: ret } +_Lambda$__0 { // Code size 12 (0xc) .maxstack 1 @@ -2691,6 +2710,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__0", ".ctor", ".ctor", ".cctor", "_Lambda$__1-0#1") g.VerifyIL(" +F { // Code size 41 (0x29) .maxstack 2 @@ -2709,6 +2729,7 @@ End Class IL_0027: stloc.3 IL_0028: ret } +_Lambda$__0 { // Code size 12 (0xc) .maxstack 8 @@ -2717,6 +2738,7 @@ End Class IL_0006: newobj 0x06000009 IL_000b: throw } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -2728,6 +2750,7 @@ End Class IL_0009: stfld 0x04000002 IL_000e: ret } +.ctor { // Code size 7 (0x7) .maxstack 8 @@ -2735,6 +2758,7 @@ End Class IL_0001: call 0x0A00000B IL_0006: ret } +.cctor { // Code size 11 (0xb) .maxstack 8 @@ -2742,6 +2766,7 @@ End Class IL_0005: stsfld 0x04000003 IL_000a: ret } +_Lambda$__1-0#1 { // Code size 7 (0x7) .maxstack 1 @@ -2776,6 +2801,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__1-0#1", ".ctor", "_Lambda$__0#2") g.VerifyIL(" +F { // Code size 32 (0x20) .maxstack 2 @@ -2791,6 +2817,7 @@ End Class IL_001d: stloc.s V_5 IL_001f: ret } +_Lambda$__1-0#1 { // Code size 12 (0xc) .maxstack 8 @@ -2799,6 +2826,7 @@ End Class IL_0006: newobj 0x06000009 IL_000b: throw } +.ctor { // Code size 7 (0x7) .maxstack 8 @@ -2806,6 +2834,7 @@ End Class IL_0001: call 0x0A00000E IL_0006: ret } +_Lambda$__0#2 { // Code size 14 (0xe) .maxstack 2 @@ -2869,6 +2898,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__2-0", "_Lambda$__2-1", ".ctor", "_Lambda$__2-0#1") g.VerifyIL(" +F { // Code size 76 (0x4c) .maxstack 2 @@ -2895,6 +2925,7 @@ End Class IL_004a: stloc.3 IL_004b: ret } +_Lambda$__2-0 { // Code size 12 (0xc) .maxstack 8 @@ -2903,6 +2934,7 @@ End Class IL_0006: newobj 0x0600000B IL_000b: throw } +_Lambda$__2-1 { // Code size 7 (0x7) .maxstack 1 @@ -2913,6 +2945,7 @@ End Class IL_0005: ldloc.0 IL_0006: ret } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -2924,6 +2957,7 @@ End Class IL_0009: stfld 0x04000004 IL_000e: ret } +_Lambda$__2-0#1 { // Code size 7 (0x7) .maxstack 1 @@ -2977,6 +3011,7 @@ End Class g.VerifyMethodDefNames("F", ".ctor", "_Lambda$__0#1") g.VerifyIL(" +F { // Code size 28 (0x1c) .maxstack 2 @@ -2992,6 +3027,7 @@ End Class IL_001a: stloc.2 IL_001b: ret } +.ctor { // Code size 7 (0x7) .maxstack 8 @@ -2999,6 +3035,7 @@ End Class IL_0001: call 0x0A000007 IL_0006: ret } +_Lambda$__0#1 { // Code size 12 (0xc) .maxstack 1 @@ -3032,6 +3069,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__0#1", ".ctor") g.VerifyIL(" +F { // Code size 4 (0x4) .maxstack 1 @@ -3040,6 +3078,7 @@ End Class IL_0002: stloc.3 IL_0003: ret } +_Lambda$__0#1 { // Code size 12 (0xc) .maxstack 8 @@ -3048,6 +3087,7 @@ End Class IL_0006: newobj 0x06000005 IL_000b: throw } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -3123,6 +3163,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__0", "_Lambda$__1", ".ctor", ".ctor", "_Lambda$__1#1") g.VerifyIL(" +F { // Code size 128 (0x80) .maxstack 3 @@ -3171,6 +3212,7 @@ End Class IL_007c: stloc.s V_5 IL_007e: br.s IL_0011 } +_Lambda$__0 { // Code size 12 (0xc) .maxstack 1 @@ -3182,6 +3224,7 @@ End Class IL_000a: ldloc.0 IL_000b: ret } +_Lambda$__1 { // Code size 12 (0xc) .maxstack 8 @@ -3190,6 +3233,7 @@ End Class IL_0006: newobj 0x06000007 IL_000b: throw } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -3201,6 +3245,7 @@ End Class IL_0009: stfld 0x04000005 IL_000e: ret } +.ctor { // Code size 22 (0x16) .maxstack 8 @@ -3214,6 +3259,7 @@ End Class IL_0010: stfld 0x04000006 IL_0015: ret } +_Lambda$__1#1 { // Code size 24 (0x18) .maxstack 2 @@ -3289,6 +3335,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__0", "_Lambda$__1", ".ctor", ".ctor", "_Lambda$__1#1") g.VerifyIL(" +F { // Code size 96 (0x60) .maxstack 3 @@ -3330,6 +3377,7 @@ End Class IL_005c: stloc.s V_5 IL_005e: br.s IL_0011 } +_Lambda$__0 { // Code size 12 (0xc) .maxstack 1 @@ -3341,6 +3389,7 @@ End Class IL_000a: ldloc.0 IL_000b: ret } +_Lambda$__1 { // Code size 12 (0xc) .maxstack 8 @@ -3349,6 +3398,7 @@ End Class IL_0006: newobj 0x0600000B IL_000b: throw } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -3360,6 +3410,7 @@ End Class IL_0009: stfld 0x04000005 IL_000e: ret } +.ctor { // Code size 22 (0x16) .maxstack 8 @@ -3373,6 +3424,7 @@ End Class IL_0010: stfld 0x04000006 IL_0015: ret } +_Lambda$__1#1 { // Code size 12 (0xc) .maxstack 1 @@ -3459,7 +3511,8 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__0", "_Lambda$__1", ".ctor", ".ctor", "_Lambda$__1#1", "_Lambda$__2#1", ".ctor") g.VerifyIL(" - { +F +{ // Code size 208 (0xd0) .maxstack 3 IL_0000: nop @@ -3528,6 +3581,7 @@ End Class IL_00c9: stloc.s V_7 IL_00cb: br IL_0014 } +_Lambda$__0 { // Code size 12 (0xc) .maxstack 1 @@ -3539,6 +3593,7 @@ End Class IL_000a: ldloc.0 IL_000b: ret } +_Lambda$__1 { // Code size 12 (0xc) .maxstack 8 @@ -3547,6 +3602,7 @@ End Class IL_0006: newobj 0x0600000B IL_000b: throw } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -3558,6 +3614,7 @@ End Class IL_0009: stfld 0x04000006 IL_000e: ret } +.ctor { // Code size 22 (0x16) .maxstack 8 @@ -3571,6 +3628,7 @@ End Class IL_0010: stfld 0x04000007 IL_0015: ret } +_Lambda$__1#1 { // Code size 29 (0x1d) .maxstack 2 @@ -3587,6 +3645,7 @@ End Class IL_001b: ldloc.0 IL_001c: ret } +_Lambda$__2#1 { // Code size 41 (0x29) .maxstack 2 @@ -3607,6 +3666,7 @@ End Class IL_0027: ldloc.0 IL_0028: ret } +.ctor { // Code size 22 (0x16) .maxstack 8 @@ -3682,6 +3742,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__0", "_Lambda$__2", "_Lambda$__1", ".ctor", "_Lambda$__2#1") g.VerifyIL(" +F { // Code size 106 (0x6a) .maxstack 3 @@ -3727,6 +3788,7 @@ End Class IL_0066: stloc.s V_6 IL_0068: br.s IL_0011 } +_Lambda$__0 { // Code size 12 (0xc) .maxstack 1 @@ -3738,6 +3800,7 @@ End Class IL_000a: ldloc.0 IL_000b: ret } +_Lambda$__2 { // Code size 12 (0xc) .maxstack 8 @@ -3746,6 +3809,7 @@ End Class IL_0006: newobj 0x06000008 IL_000b: throw } +_Lambda$__1 { // Code size 12 (0xc) .maxstack 1 @@ -3757,6 +3821,7 @@ End Class IL_000a: ldloc.0 IL_000b: ret } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -3768,6 +3833,7 @@ End Class IL_0009: stfld 0x04000005 IL_000e: ret } +_Lambda$__2#1 { // Code size 14 (0xe) .maxstack 2 @@ -3834,6 +3900,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__0") g.VerifyIL(" +F { // Code size 35 (0x23) .maxstack 2 @@ -3852,6 +3919,7 @@ End Class IL_0021: stloc.3 IL_0022: ret } +_Lambda$__0 { // Code size 19 (0x13) .maxstack 2 @@ -3916,6 +3984,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__0") g.VerifyIL(" +F { // Code size 35 (0x23) .maxstack 2 @@ -3934,6 +4003,7 @@ End Class IL_0021: stloc.2 IL_0022: ret } +_Lambda$__0 { // Code size 19 (0x13) .maxstack 2 @@ -3997,6 +4067,7 @@ End Class g.VerifyMethodDefNames("F", "_Lambda$__1-0", ".ctor", "_Lambda$__1-0#1") g.VerifyIL(" +F { // Code size 39 (0x27) .maxstack 2 @@ -4013,6 +4084,7 @@ End Class IL_0025: stloc.1 IL_0026: ret } +_Lambda$__1-0 { // Code size 12 (0xc) .maxstack 8 @@ -4021,6 +4093,7 @@ End Class IL_0006: newobj 0x06000006 IL_000b: throw } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -4032,6 +4105,7 @@ End Class IL_0009: stfld 0x04000003 IL_000e: ret } +_Lambda$__1-0#1 { // Code size 15 (0xf) .maxstack 1 diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.vb index 8e3998babc5e9..8193d204d35d7 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.vb @@ -1475,6 +1475,7 @@ End Class }) g.VerifyIL(" +add_E, remove_E, raise_E { // Code size 13 (0xd) .maxstack 8 @@ -1483,6 +1484,7 @@ End Class IL_0007: newobj 0x06000005 IL_000c: throw } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -1537,6 +1539,7 @@ End Class }) g.VerifyIL(" +add_E { // Code size 10 (0xa) .maxstack 8 @@ -1546,6 +1549,7 @@ End Class IL_0008: nop IL_0009: ret } +remove_E { // Code size 10 (0xa) .maxstack 8 @@ -1555,6 +1559,7 @@ End Class IL_0008: nop IL_0009: ret } +raise_E { // Code size 10 (0xa) .maxstack 8 @@ -1649,6 +1654,7 @@ End Class }) g.VerifyIL(" +add_E, remove_E { // Code size 13 (0xd) .maxstack 8 @@ -1657,6 +1663,7 @@ End Class IL_0007: newobj 0x06000007 IL_000c: throw } +add_E { // Code size 10 (0xa) .maxstack 8 @@ -1666,6 +1673,7 @@ End Class IL_0008: nop IL_0009: ret } +remove_E { // Code size 10 (0xa) .maxstack 8 @@ -1675,6 +1683,7 @@ End Class IL_0008: nop IL_0009: ret } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -1736,6 +1745,7 @@ End Class }) g.VerifyIL(" +add_E { // Code size 10 (0xa) .maxstack 8 @@ -1745,6 +1755,7 @@ End Class IL_0008: nop IL_0009: ret } +remove_E { // Code size 13 (0xd) .maxstack 8 @@ -1754,6 +1765,7 @@ End Class IL_000b: nop IL_000c: ret } +add_E, remove_E { // Code size 13 (0xd) .maxstack 8 @@ -2337,6 +2349,7 @@ End Class }) g.VerifyIL(" +get_P, set_P { // Code size 13 (0xd) .maxstack 8 @@ -2345,6 +2358,7 @@ End Class IL_0007: newobj 0x06000006 IL_000c: throw } +get_P { // Code size 15 (0xf) .maxstack 1 @@ -2358,6 +2372,7 @@ End Class IL_000d: ldloc.0 IL_000e: ret } +set_P { // Code size 10 (0xa) .maxstack 8 @@ -2367,6 +2382,7 @@ End Class IL_0008: nop IL_0009: ret } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -2429,6 +2445,7 @@ End Class }) g.VerifyIL(" +get_P { // Code size 15 (0xf) .maxstack 1 @@ -2442,6 +2459,7 @@ End Class IL_000d: ldloc.0 IL_000e: ret } +set_P { // Code size 13 (0xd) .maxstack 8 @@ -2451,6 +2469,7 @@ End Class IL_000b: nop IL_000c: ret } +get_P, set_P { // Code size 13 (0xd) .maxstack 8 @@ -2522,6 +2541,7 @@ End Class }) g.VerifyIL(" +get_P, set_P { // Code size 13 (0xd) .maxstack 8 @@ -2530,6 +2550,7 @@ End Class IL_0007: newobj 0x06000004 IL_000c: throw } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -2576,6 +2597,7 @@ End Class }) g.VerifyIL(" +get_P { // Code size 7 (0x7) .maxstack 1 @@ -2649,6 +2671,7 @@ End Class }) g.VerifyIL(" +get_P { // Code size 13 (0xd) .maxstack 8 @@ -2657,6 +2680,7 @@ End Class IL_0007: newobj 0x06000004 IL_000c: throw } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -2703,6 +2727,7 @@ End Class }) g.VerifyIL(" +get_P { // Code size 7 (0x7) .maxstack 1 @@ -5980,6 +6005,7 @@ End Class }) g.VerifyIL(" +F { // Code size 39 (0x27) .maxstack 2 @@ -5996,6 +6022,7 @@ End Class IL_0025: stloc.2 IL_0026: ret } +_Lambda$__1-0 { // Code size 12 (0xc) .maxstack 8 @@ -6004,6 +6031,7 @@ End Class IL_0006: newobj 0x06000007 IL_000b: throw } +_Lambda$__1-1 { // Code size 9 (0x9) .maxstack 8 @@ -6013,6 +6041,7 @@ End Class IL_0007: nop IL_0008: ret } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -6086,33 +6115,36 @@ End Class }) g.VerifyIL(" +F { - // Code size 13 (0xd) - .maxstack 8 - IL_0000: ldstr 0x70000005 - IL_0005: ldc.i4.s -2 - IL_0007: newobj 0x06000006 - IL_000c: throw - } - { - // Code size 12 (0xc) - .maxstack 8 - IL_0000: ldstr 0x7000014E - IL_0005: ldc.i4.m1 - IL_0006: newobj 0x06000006 - IL_000b: throw - } - { - // Code size 15 (0xf) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldarg.1 - IL_0002: call 0x0A000008 - IL_0007: ldarg.0 - IL_0008: ldarg.2 - IL_0009: stfld 0x04000003 - IL_000e: ret - } + // Code size 13 (0xd) + .maxstack 8 + IL_0000: ldstr 0x70000005 + IL_0005: ldc.i4.s -2 + IL_0007: newobj 0x06000006 + IL_000c: throw +} +_Lambda$__1-0 +{ + // Code size 12 (0xc) + .maxstack 8 + IL_0000: ldstr 0x7000014E + IL_0005: ldc.i4.m1 + IL_0006: newobj 0x06000006 + IL_000b: throw +} +.ctor +{ + // Code size 15 (0xf) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call 0x0A000008 + IL_0007: ldarg.0 + IL_0008: ldarg.2 + IL_0009: stfld 0x04000003 + IL_000e: ret +} ") End Sub). AddGeneration(' 2 @@ -6160,6 +6192,7 @@ End Class }) g.VerifyIL(" +F { // Code size 39 (0x27) .maxstack 2 @@ -6176,6 +6209,7 @@ End Class IL_0025: stloc.0 IL_0026: ret } +.ctor { // Code size 7 (0x7) .maxstack 8 @@ -6183,6 +6217,7 @@ End Class IL_0001: call 0x0A00000B IL_0006: ret } +_Lambda$__1#2-0#2 { // Code size 9 (0x9) .maxstack 8 @@ -6233,6 +6268,7 @@ End Class }) g.VerifyIL(" +F { // Code size 13 (0xd) .maxstack 8 @@ -6241,6 +6277,7 @@ End Class IL_0007: newobj 0x06000006 IL_000c: throw } +_Lambda$__1#2-0#2 { // Code size 12 (0xc) .maxstack 8 @@ -6336,6 +6373,7 @@ End Class }) g.VerifyIL(" +F { // Code size 13 (0xd) .maxstack 8 @@ -6344,6 +6382,7 @@ End Class IL_0007: newobj 0x06000006 IL_000c: throw } +_Lambda$__1#1-0#1 { // Code size 12 (0xc) .maxstack 8 @@ -6352,6 +6391,7 @@ End Class IL_0006: newobj 0x06000006 IL_000b: throw } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -6478,6 +6518,7 @@ End Class }) g.VerifyIL(" +F { // Code size 13 (0xd) .maxstack 8 @@ -6486,6 +6527,7 @@ End Class IL_0007: newobj 0x06000009 IL_000c: throw } +_Lambda$__1-0, _Lambda$__1-1#1, _Lambda$__1-2#2 { // Code size 12 (0xc) .maxstack 8 @@ -6494,6 +6536,7 @@ End Class IL_0006: newobj 0x06000009 IL_000b: throw } +.ctor { // Code size 15 (0xf) .maxstack 8 @@ -6534,6 +6577,7 @@ End Class g.VerifyMemberRefNames(".ctor", "$I1#4-0#4", "$I", "_Lambda$__1#4-0#4", ".ctor", ".ctor", ".ctor", "$I", "WriteLine") g.VerifyIL(" +F { // Code size 50 (0x32) .maxstack 2 @@ -6554,6 +6598,7 @@ End Class IL_0030: ldloc.0 IL_0031: ret } +.ctor { // Code size 7 (0x7) .maxstack 8 @@ -6561,6 +6606,7 @@ End Class IL_0001: call 0x0A000029 IL_0006: ret } +.cctor { // Code size 11 (0xb) .maxstack 8 @@ -6568,6 +6614,7 @@ End Class IL_0005: stsfld 0x0A00002B IL_000a: ret } +_Lambda$__1#4-0#4 { // Code size 9 (0x9) .maxstack 8 @@ -6617,6 +6664,7 @@ End Class }) g.VerifyIL(" +F { // Code size 13 (0xd) .maxstack 8 @@ -6625,6 +6673,7 @@ End Class IL_0007: newobj 0x06000009 IL_000c: throw } +_Lambda$__1#4-0#4 { // Code size 12 (0xc) .maxstack 8 @@ -7319,6 +7368,7 @@ End Class", v.VerifyTypeRefNames("Object") v.VerifyIL(" +M { // Code size 13 (0xd) .maxstack 8 @@ -7371,6 +7421,7 @@ End Class", v.VerifyTypeRefNames("Exception", "Object") v.VerifyIL(" +M { // Code size 13 (0xd) .maxstack 8 @@ -7379,6 +7430,7 @@ End Class", IL_0007: newobj 0x06000003 IL_000c: throw } +.ctor { // Code size 10 (0xa) .maxstack 8 @@ -7436,7 +7488,7 @@ End Class", - Public Sub PrivateImplDetails_DataFields_Arrays() + Public Sub PrivateImplDetails_DataFields_Arrays_FieldRvaNotSupported() Using New EditAndContinueTest(). AddBaseline( source:=" @@ -7536,6 +7588,88 @@ End Class + Public Sub PrivateImplDetails_DataFields_Arrays_FieldRvaSupported() + Using New EditAndContinueTest(). + AddBaseline( + source:=" +Class C + Dim b As Byte() = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } +End Class +", + validator:= + Sub(g) + g.VerifyTypeDefNames("", "C", "", "__StaticArrayInitTypeSize=10") + g.VerifyFieldDefNames("b", "1F825AA2F0020EF7CF91DFA30DA4668D791C5D4824FC8E41354B89EC05795AB3") + g.VerifyMethodDefNames(".ctor") + End Sub). + AddGeneration( + source:=" +Class C + Dim b As Byte() = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } +End Class +", + edits:= + { + Edit(SemanticEditKind.Update, symbolProvider:=Function(c) c.GetMember("C..ctor")) + }, + validator:= + Sub(g) + g.VerifyTypeDefNames("#1", "__StaticArrayInitTypeSize=11") + g.VerifyFieldDefNames("78A6273103D17C39A0B6126E226CEC70E33337F4BC6A38067401B54A33E78EAD") + g.VerifyMethodDefNames(".ctor") + + g.VerifyEncLogDefinitions( + { + Row(5, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(6, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddField), + Row(3, TableIndex.Field, EditAndContinueOperation.Default), + Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(2, TableIndex.ClassLayout, EditAndContinueOperation.Default), + Row(2, TableIndex.FieldRva, EditAndContinueOperation.Default), + Row(2, TableIndex.NestedClass, EditAndContinueOperation.Default) + }) + + g.VerifyEncMapDefinitions( + { + Handle(5, TableIndex.TypeDef), + Handle(6, TableIndex.TypeDef), + Handle(3, TableIndex.Field), + Handle(1, TableIndex.MethodDef), + Handle(5, TableIndex.CustomAttribute), + Handle(2, TableIndex.ClassLayout), + Handle(2, TableIndex.FieldRva), + Handle(2, TableIndex.NestedClass) + }) + + g.VerifyIL("C..ctor", " +{ + // Code size 32 (0x20) + .maxstack 4 + IL_0000: ldarg.0 + IL_0001: call ""Sub Object..ctor()"" + IL_0006: nop + IL_0007: ldarg.0 + IL_0008: ldc.i4.s 11 + IL_000a: newarr ""Byte"" + IL_000f: dup + IL_0010: ldtoken ""#1.__StaticArrayInitTypeSize=11 #1.78A6273103D17C39A0B6126E226CEC70E33337F4BC6A38067401B54A33E78EAD"" + IL_0015: call ""Sub System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)"" + IL_001a: stfld ""C.b As Byte()"" + IL_001f: ret +}") + End Sub, + options:= + New EmitDifferenceOptions() With + { + .EmitFieldRva = True + }). + Verify() + End Using + End Sub + + Public Sub PrivateImplDetails_ComputeStringHash() Using New EditAndContinueTest(). AddBaseline( diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/EmitErrorTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/EmitErrorTests.vb index 20d5896b8780e..649cc8877b86c 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/EmitErrorTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/EmitErrorTests.vb @@ -597,10 +597,13 @@ End Module") Dim compilation = CreateEmptyCompilationWithReferences(VisualBasicSyntaxTree.ParseText(source.ToString()), {MscorlibRef, SystemRef, MsvbRef}) - AssertTheseEmitDiagnostics(compilation, - -BC37255: Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string or XML literals. -) + Dim expectedDiagnostics = + { + Diagnostic(ERRID.ERR_TooManyUserStrings, """" & New String("K"c, 1000000) & """").WithLocation(13, 33), + Diagnostic(ERRID.ERR_TooManyUserStrings, """" & New String("L"c, 1000000) & """").WithLocation(14, 33) + } + + CreateCompilation(source.ToString()).VerifyEmitDiagnostics(expectedDiagnostics) End Sub #End Region diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/EEAssemblyBuilder.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/EEAssemblyBuilder.cs index 6dfffefaacde8..b0bcd47af9095 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/EEAssemblyBuilder.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/EEAssemblyBuilder.cs @@ -67,6 +67,7 @@ protected override Cci.IModuleReference TranslateModule(ModuleSymbol symbol, Dia internal override bool IgnoreAccessibility => true; public override EmitBaseline? PreviousGeneration => null; public override SymbolChanges? EncSymbolChanges => null; + public override bool FieldRvaSupported => true; public override INamedTypeSymbolInternal? TryGetOrCreateSynthesizedHotReloadExceptionType() => null; diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ReferencedModulesTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ReferencedModulesTests.cs index 733ed84419182..07102f9c9e0f8 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ReferencedModulesTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ReferencedModulesTests.cs @@ -1543,6 +1543,7 @@ public override IEnumerable GetTopLevelSourceTypeDefin public override SymbolChanges EncSymbolChanges => _builder.EncSymbolChanges; public override EmitBaseline PreviousGeneration => _builder.PreviousGeneration; + public override bool FieldRvaSupported => _builder.FieldRvaSupported; public override ISourceAssemblySymbolInternal SourceAssemblyOpt => _builder.SourceAssemblyOpt; diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/EEAssemblyBuilder.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/EEAssemblyBuilder.vb index f3837978bc0db..6fb8bc777acec 100644 --- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/EEAssemblyBuilder.vb +++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/EEAssemblyBuilder.vb @@ -81,6 +81,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator End Get End Property + Public Overrides ReadOnly Property FieldRvaSupported As Boolean + Get + Return True + End Get + End Property + Public Overrides Function TryGetOrCreateSynthesizedHotReloadExceptionType() As INamedTypeSymbolInternal Return Nothing End Function diff --git a/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ReferencedModulesTests.vb b/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ReferencedModulesTests.vb index 035e5a7d149dc..e2afb96c254f2 100644 --- a/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ReferencedModulesTests.vb +++ b/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ReferencedModulesTests.vb @@ -969,7 +969,13 @@ End Class" Public Overrides ReadOnly Property PreviousGeneration As EmitBaseline Get - Return Nothing + Return _builder.PreviousGeneration + End Get + End Property + + Public Overrides ReadOnly Property FieldRvaSupported As Boolean + Get + Return _builder.FieldRvaSupported End Get End Property diff --git a/src/Features/Core/Portable/EditAndContinue/EditAndContinueCapabilities.cs b/src/Features/Core/Portable/EditAndContinue/EditAndContinueCapabilities.cs index 36607b513ff06..5666e53e55810 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditAndContinueCapabilities.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditAndContinueCapabilities.cs @@ -70,6 +70,12 @@ internal enum EditAndContinueCapabilities /// The runtime supports adding to InterfaceImpl table. /// AddExplicitInterfaceImplementation = 1 << 10, + + /// + /// The runtime supports adding FieldRva table entry. This allows compiler to emit better code for certain features including + /// array initializers, collection expressions, UTF8 string literals and data section string literals. + /// + AddFieldRva = 1 << 11, } internal static class EditAndContinueCapabilitiesParser @@ -93,6 +99,7 @@ public static EditAndContinueCapabilities Parse(ImmutableArray capabilit nameof(EditAndContinueCapabilities.GenericUpdateMethod) => EditAndContinueCapabilities.GenericUpdateMethod, nameof(EditAndContinueCapabilities.GenericAddFieldToExistingType) => EditAndContinueCapabilities.GenericAddFieldToExistingType, nameof(EditAndContinueCapabilities.AddExplicitInterfaceImplementation) => EditAndContinueCapabilities.AddExplicitInterfaceImplementation, + nameof(EditAndContinueCapabilities.AddFieldRva) => EditAndContinueCapabilities.AddFieldRva, // To make it eaiser for runtimes to specify more broad capabilities "AddDefinitionToExistingType" => EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddStaticFieldToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType, @@ -132,6 +139,9 @@ public static ImmutableArray ToStringArray(this EditAndContinueCapabilit if (capabilities.HasFlag(EditAndContinueCapabilities.AddExplicitInterfaceImplementation)) builder.Add(nameof(EditAndContinueCapabilities.AddExplicitInterfaceImplementation)); + if (capabilities.HasFlag(EditAndContinueCapabilities.AddFieldRva)) + builder.Add(nameof(EditAndContinueCapabilities.AddFieldRva)); + return builder.ToImmutableAndClear(); } } diff --git a/src/Features/Core/Portable/EditAndContinue/EditSession.cs b/src/Features/Core/Portable/EditAndContinue/EditSession.cs index cfdd757268587..9b7c90fd750ee 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditSession.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditSession.cs @@ -1097,6 +1097,7 @@ void UpdateChangedDocumentsStaleness(bool isStale) metadataStream, ilStream, pdbStream, + new EmitDifferenceOptions() { EmitFieldRva = capabilities.HasFlag(EditAndContinueCapabilities.AddFieldRva) }, cancellationToken); Telemetry.LogEmitDifferenceTime(emitDifferenceTimer.Elapsed); diff --git a/src/Features/TestUtilities/EditAndContinue/EditAndContinueTestVerifier.cs b/src/Features/TestUtilities/EditAndContinue/EditAndContinueTestVerifier.cs index 835d7210d8b64..eb7321a98e6f6 100644 --- a/src/Features/TestUtilities/EditAndContinue/EditAndContinueTestVerifier.cs +++ b/src/Features/TestUtilities/EditAndContinue/EditAndContinueTestVerifier.cs @@ -40,12 +40,19 @@ internal abstract class EditAndContinueTestVerifier EditAndContinueCapabilities.ChangeCustomAttributes | EditAndContinueCapabilities.UpdateParameters; - public const EditAndContinueCapabilities AllRuntimeCapabilities = + public const EditAndContinueCapabilities Net8RuntimeCapabilities = Net6RuntimeCapabilities | EditAndContinueCapabilities.GenericAddMethodToExistingType | EditAndContinueCapabilities.GenericUpdateMethod | EditAndContinueCapabilities.GenericAddFieldToExistingType; + public const EditAndContinueCapabilities Net10RuntimeCapabilities = + Net8RuntimeCapabilities | + EditAndContinueCapabilities.AddFieldRva; + + public const EditAndContinueCapabilities AllRuntimeCapabilities = + Net10RuntimeCapabilities; + public AbstractEditAndContinueAnalyzer Analyzer { get; } protected EditAndContinueTestVerifier(Action? faultInjector) diff --git a/src/Test/PdbUtilities/EditAndContinue/EditAndContinueTest.GenerationVerifier.cs b/src/Test/PdbUtilities/EditAndContinue/EditAndContinueTest.GenerationVerifier.cs index 17cf4dbc1d53b..63be4ad35bae0 100644 --- a/src/Test/PdbUtilities/EditAndContinue/EditAndContinueTest.GenerationVerifier.cs +++ b/src/Test/PdbUtilities/EditAndContinue/EditAndContinueTest.GenerationVerifier.cs @@ -181,11 +181,22 @@ internal void VerifyPdb(string qualifiedMemberName, string expectedPdb, PdbValid internal void VerifyCustomDebugInformation(string qualifiedMemberName, string expectedPdb) => VerifyPdb(qualifiedMemberName, expectedPdb, PdbValidationOptions.ExcludeDocuments | PdbValidationOptions.ExcludeSequencePoints | PdbValidationOptions.ExcludeScopes); - internal void VerifyIL(string expectedIL) + internal void VerifyEncFieldRvaData(string expected) => Verify(() => { Debug.Assert(generationInfo.CompilationDifference != null); - generationInfo.CompilationDifference.VerifyIL(expectedIL); + + var actual = ILValidation.DumpEncDeltaFieldData(generationInfo.CompilationDifference.ILDelta, readers); + AssertEx.AssertEqualToleratingWhitespaceDifferences(expected, actual, escapeQuotes: false); + }); + + internal void VerifyIL(string expected) + => Verify(() => + { + Debug.Assert(generationInfo.CompilationDifference != null); + + var actual = ILValidation.DumpEncDeltaMethodBodies(generationInfo.CompilationDifference.ILDelta, readers); + AssertEx.AssertEqualToleratingWhitespaceDifferences(expected, actual, escapeQuotes: false); }); internal void VerifyIL(string qualifiedMemberName, string expectedIL) diff --git a/src/Test/PdbUtilities/EditAndContinue/EditAndContinueTest.cs b/src/Test/PdbUtilities/EditAndContinue/EditAndContinueTest.cs index d9f5de65aa9bd..6734d072eb3db 100644 --- a/src/Test/PdbUtilities/EditAndContinue/EditAndContinueTest.cs +++ b/src/Test/PdbUtilities/EditAndContinue/EditAndContinueTest.cs @@ -10,6 +10,7 @@ using System.Reflection.Metadata; using System.Runtime.InteropServices; using System.Text; +using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; @@ -70,16 +71,16 @@ internal TSelf AddBaseline(string source, Action? validator return This; } - internal TSelf AddGeneration(string source, SemanticEditDescription[] edits, Action validator) - => AddGeneration(source, _ => edits, validator); + internal TSelf AddGeneration(string source, SemanticEditDescription[] edits, Action validator, EmitDifferenceOptions? options = null) + => AddGeneration(source, _ => edits, validator, options); - internal TSelf AddGeneration(string source, Func edits, Action validator) - => AddGeneration(source, edits, validator, expectedErrors: []); + internal TSelf AddGeneration(string source, Func edits, Action validator, EmitDifferenceOptions? options = null) + => AddGeneration(source, edits, validator, expectedErrors: [], options); - internal TSelf AddGeneration(string source, SemanticEditDescription[] edits, DiagnosticDescription[] expectedErrors) - => AddGeneration(source, _ => edits, validator: static _ => { }, expectedErrors); + internal TSelf AddGeneration(string source, SemanticEditDescription[] edits, DiagnosticDescription[] expectedErrors, EmitDifferenceOptions? options = null) + => AddGeneration(source, _ => edits, validator: static _ => { }, expectedErrors, options); - private TSelf AddGeneration(string source, Func edits, Action validator, DiagnosticDescription[] expectedErrors) + private TSelf AddGeneration(string source, Func edits, Action validator, DiagnosticDescription[] expectedErrors, EmitDifferenceOptions? options = null) { _hasVerified = false; @@ -97,7 +98,7 @@ private TSelf AddGeneration(string source, Func d.Severity == DiagnosticSeverity.Error).Verify(expectedErrors); if (expectedErrors is not [])