| File: Actions\GrammarActions.MethodBodies.Directives.cs | Web Access |
| Project: ILAssembler.csproj (ILAssembler) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; namespace ILAssembler; internal sealed partial class GrammarActions { internal void EndLocalsDirective( CILParser.LocalsDeclContext context, int initialSyntaxErrorCount) { bool hasSyntaxError = HasSyntaxErrorsSince(initialSyntaxErrorCount) || context.exception is not null; if (hasSyntaxError || _currentMethod is null || context.arguments is null) { return; } if (context.initialize is not null) { _currentMethod.Definition.BodyAttributes = MethodBodyAttributes.InitLocals; } Dictionary<string, int> localsScope; if (_currentMethod.LocalsScopes.Count > 0) { localsScope = _currentMethod.LocalsScopes[^1]; } else { localsScope = new(); _currentMethod.LocalsScopes.Add(localsScope); } ImmutableArray<SignatureArg> locals = MaterializeSignatureArguments(context.arguments.Value); foreach (SignatureArg local in locals) { if (local.Name is not null) { localsScope.TryAdd(local.Name, _currentMethod.AllLocals.Count); } _currentMethod.AllLocals.Add(local); } } internal void EndExportDirective( CILParser.ExportDeclContext context, int initialSyntaxErrorCount) { bool hasSyntaxError = HasSyntaxErrorsSince(initialSyntaxErrorCount) || context.exception is not null; if (_currentMethod is null) { return; } _currentMethod.Definition.ExportOrdinal = -1; _currentMethod.Definition.ExportAlias = null; _exportDirectiveContexts.Remove(_currentMethod.Definition); if (hasSyntaxError || context.ordinal is null) { return; } int diagnosticCount = _diagnostics.Count; int ordinal = ParseInt32(context.ordinal.Start); string? alias = context.alias is null ? null : ParseIdentifier(context.alias.Start); if (_diagnostics.Count != diagnosticCount) { return; } if (ordinal <= 0) { ReportError( DiagnosticIds.InvalidExportOrdinal, string.Format(DiagnosticMessageTemplates.InvalidExportOrdinal, ordinal), context); return; } _currentMethod.Definition.ExportOrdinal = ordinal; _currentMethod.Definition.ExportAlias = alias; _exportDirectiveContexts[_currentMethod.Definition] = context; } internal void EndVTableEntryDirective( CILParser.VtentryDeclContext context, int initialSyntaxErrorCount) { bool hasSyntaxError = HasSyntaxErrorsSince(initialSyntaxErrorCount) || context.exception is not null; if (_currentMethod is null) { return; } _currentMethod.Definition.VTableEntry = 0; _currentMethod.Definition.VTableSlot = 0; _vtableEntryDirectiveContexts.Remove(_currentMethod.Definition); if (hasSyntaxError || context.table is null || context.slot is null) { return; } int diagnosticCount = _diagnostics.Count; int vtableEntry = ParseInt32(context.table.Start); int vtableSlot = ParseInt32(context.slot.Start); if (_diagnostics.Count != diagnosticCount) { return; } _currentMethod.Definition.VTableEntry = vtableEntry; _currentMethod.Definition.VTableSlot = vtableSlot; _vtableEntryDirectiveContexts[_currentMethod.Definition] = context; } internal void EndOverrideDirective( CILParser.OverrideDeclContext context, int initialSyntaxErrorCount) { bool hasSyntaxError = HasSyntaxErrorsSince(initialSyntaxErrorCount) || context.exception is not null; if (hasSyntaxError || _currentMethod is null || context.owner is null || context.name is null || _currentTypeDefinition.PeekOrDefault() is not { } currentType) { return; } BlobBuilder signature = _currentMethod.Definition.MethodSignature!; if (context.convention is not null) { if (context.returnType is null || context.arity is null || context.arguments is null) { return; } signature = BuildOverrideSignature( context.convention.Value, context.returnType.Value, context.arity.Value, context.arguments.Value); } EntityRegistry.TypeEntity owner = ResolveTypeSpecification(context.owner.Value); EntityRegistry.MemberReferenceEntity declaration = _entityRegistry.CreateLazilyRecordedMemberReference(owner, context.name.Value, signature); currentType.MethodImplementations.Add( EntityRegistry.CreateUnrecordedMethodImplementation(_currentMethod.Definition, declaration)); } private BlobBuilder BuildOverrideSignature( byte callingConvention, TypeValue returnType, int genericArity, ImmutableArray<SignatureArgumentValue> signatureArguments) { BlobBuilder signature = new(); byte header = callingConvention; if (genericArity > 0) { header |= (byte)SignatureAttributes.Generic; } signature.WriteByte(header); if (genericArity > 0) { signature.WriteCompressedInteger(genericArity); } ImmutableArray<SignatureArg> arguments = MaterializeSignatureArguments(signatureArguments); signature.WriteCompressedInteger(arguments.Length); MaterializeType(returnType).WriteContentTo(signature); foreach (SignatureArg argument in arguments) { argument.SignatureBlob.WriteContentTo(signature); } return signature; } #pragma warning disable CA1822 // Parser actions are invoked through the per-parser GrammarActions instance. internal void AddCustomAttributeApplication( ImmutableArray<CustomAttributeApplicationValue>.Builder attributes, CILParser.CustomAttrDeclContext attribute) => attributes.Add(new( attribute.Value, attribute.Start, attribute.HasSyntaxError)); #pragma warning restore CA1822 internal void EndParameterDirective( CILParser.ParameterDeclContext context, ImmutableArray<CustomAttributeApplicationValue> attributes, int initialSyntaxErrorCount) { bool hasSyntaxError = HasSyntaxErrorsSince(initialSyntaxErrorCount) || context.exception is not null; if (hasSyntaxError || _currentMethod is null) { return; } if (context.genericIndex is not null || context.genericName is not null) { EntityRegistry.GenericParameterEntity? parameter = ResolveMethodGenericParameter( context.genericIndex, context.genericName?.Value, context); if (parameter is not null) { ApplyCustomAttributes(attributes, parameter); } return; } if (context.constraintIndex is not null || context.constraintName is not null) { EntityRegistry.GenericParameterEntity? parameter = ResolveMethodGenericParameter( context.constraintIndex, context.constraintName?.Value, context); if (parameter is null || context.constraintType is null) { return; } EntityRegistry.TypeEntity baseType = ResolveTypeSpecification(context.constraintType.Value); EntityRegistry.GenericParameterConstraintEntity? constraint = parameter.Constraints.FirstOrDefault(candidate => candidate.BaseType == baseType); if (constraint is null) { constraint = EntityRegistry.CreateGenericConstraint(baseType); constraint.Owner = parameter; parameter.Constraints.Add(constraint); _currentMethod.Definition.GenericParameterConstraints.Add(constraint); } ApplyCustomAttributes(attributes, constraint); return; } if (context.parameterIndex is null || context.initializer is null) { return; } int index = ParseInt32(context.parameterIndex.Start); if ((uint)index >= (uint)_currentMethod.Definition.Parameters.Count) { ReportError( DiagnosticIds.ParameterIndexOutOfRange, string.Format(DiagnosticMessageTemplates.ParameterIndexOutOfRange, index), context); return; } EntityRegistry.ParameterEntity parameterEntity = _currentMethod.Definition.Parameters[index]; FieldInitializerValue initializer = GetInitializerValue(context.initializer); if (initializer.HasValue) { parameterEntity.ConstantValue = initializer.ConstantValue; parameterEntity.HasConstant = true; } foreach (CustomAttributeApplicationValue application in attributes) { if (application.HasSyntaxError) { continue; } EntityRegistry.CustomAttributeEntity? attribute = MaterializeCustomAttributeDeclaration( application.Value, application.Location); if (attribute is not null) { attribute.Owner ??= parameterEntity; parameterEntity.HasCustomAttributes = true; } } } private EntityRegistry.GenericParameterEntity? ResolveMethodGenericParameter( CILParser.Int32Context? indexContext, string? name, CILParser.ParameterDeclContext diagnosticContext) { Debug.Assert(_currentMethod is not null); if (indexContext is not null) { int index = ParseInt32(indexContext.Start); if ((uint)index >= (uint)_currentMethod.Definition.GenericParameters.Count) { ReportError( DiagnosticIds.GenericParameterIndexOutOfRange, string.Format(DiagnosticMessageTemplates.GenericParameterIndexOutOfRange, index), diagnosticContext); return null; } return _currentMethod.Definition.GenericParameters[index]; } EntityRegistry.GenericParameterEntity? parameter = _currentMethod.Definition.GenericParameters.FirstOrDefault(candidate => candidate.Name == name); if (parameter is null) { ReportError( DiagnosticIds.UnknownGenericParameter, string.Format(DiagnosticMessageTemplates.UnknownGenericParameter, name), diagnosticContext); } return parameter; } private void ApplyCustomAttributes( ImmutableArray<CustomAttributeApplicationValue> attributes, EntityRegistry.EntityBase owner) { foreach (CustomAttributeApplicationValue application in attributes) { if (application.HasSyntaxError) { continue; } EntityRegistry.CustomAttributeEntity? attribute = MaterializeCustomAttributeDeclaration( application.Value, application.Location); if (attribute is not null) { attribute.Owner ??= owner; } } } #pragma warning disable CA1822 // Parser actions own these directive side effects. internal void ProcessMethodDataDeclaration(CILParser.DataDeclContext context) => _ = context; #pragma warning restore CA1822 internal void ProcessMethodSecurityDeclaration(CILParser.SecDeclContext context) { if (_currentMethod is null || context.HasSyntaxError) { return; } EntityRegistry.DeclarativeSecurityAttributeEntity? security = MaterializeSecurityDeclaration(context); security?.Parent = _currentMethod.Definition; } #pragma warning disable CA1822 // Parser actions own these directive side effects. internal void ProcessMethodSourceDirective(CILParser.ExtSourceSpecContext context) => _ = context; internal void ProcessMethodLanguageDirective(CILParser.LanguageDeclContext context) => _ = context; #pragma warning restore CA1822 internal void ProcessMethodCustomAttribute(CILParser.CustomDescrInMethodBodyContext context) { if (_currentMethod is null || context.HasSyntaxError) { return; } EntityRegistry.CustomAttributeEntity? attribute = MaterializeMethodBodyCustomAttributeDeclaration(context); if (attribute is not null) { attribute.Owner ??= _currentMethod.Definition; } } }