Skip to content

Add support for FieldRva to EnC delta #78033

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
May 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -5314,6 +5314,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_TooManyUserStrings" xml:space="preserve">
<value>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'.</value>
</data>
<data name="ERR_TooManyUserStrings_RestartRequired" xml:space="preserve">
<value>Combined length of user strings used by the program exceeds allowed limit. Adding a string literal requires restarting the application.</value>
</data>
<data name="ERR_PatternNullableType" xml:space="preserve">
<value>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</value>
</data>
Expand Down
18 changes: 9 additions & 9 deletions src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -444,25 +444,25 @@ 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;

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();
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
26 changes: 12 additions & 14 deletions src/Compilers/CSharp/Portable/CodeGen/EmitArrayInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ private void EmitArrayInitializers(ArrayTypeSymbol arrayType, BoundArrayInitiali
{
ImmutableArray<byte> data = this.GetRawData(initExprs);

_builder.EmitArrayBlockInitializer(data, inits.Syntax, _diagnostics.DiagnosticBag);
_builder.EmitArrayBlockInitializer(data, inits.Syntax);

if (initializationStyle == ArrayInitializerStyle.Mixed)
{
Expand Down Expand Up @@ -245,10 +245,9 @@ private bool EnableEnumArrayBlockInitialization

private ArrayInitializerStyle ShouldEmitBlockInitializer(TypeSymbol elementType, ImmutableArray<BoundExpression> 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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -617,7 +615,7 @@ private bool TryEmitOptimizedReadonlySpanCreation(NamedTypeSymbol spanType, Boun
// call ReadOnlySpan<elementType> RuntimeHelpers::CreateSpan<elementType>(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;
Expand Down Expand Up @@ -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);

Expand All @@ -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<T>(array)
Expand Down Expand Up @@ -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);

Expand All @@ -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<T>(array)
Expand Down
70 changes: 25 additions & 45 deletions src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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);

Expand All @@ -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)
Expand All @@ -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()
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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);
}

Expand Down
Loading