| File: Emitter\Model\FieldSymbolAdapter.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// 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. #nullable disable using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.Emit; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols { internal partial class #if DEBUG FieldSymbolAdapter : SymbolAdapter, #else FieldSymbol : #endif Cci.IFieldReference, Cci.IFieldDefinition, Cci.ITypeMemberReference, Cci.ITypeDefinitionMember, Cci.ISpecializedFieldReference { public bool IsEncDeleted => false; Cci.ITypeReference Cci.IFieldReference.GetType(EmitContext context) { PEModuleBuilder moduleBeingBuilt = (PEModuleBuilder)context.Module; TypeWithAnnotations fieldTypeWithAnnotations = AdaptedFieldSymbol.TypeWithAnnotations; var customModifiers = fieldTypeWithAnnotations.CustomModifiers; var isFixed = AdaptedFieldSymbol.IsFixedSizeBuffer; var implType = isFixed ? AdaptedFieldSymbol.FixedImplementationType(moduleBeingBuilt) : fieldTypeWithAnnotations.Type; var type = moduleBeingBuilt.Translate(implType, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNode, diagnostics: context.Diagnostics); if (isFixed || customModifiers.Length == 0) { return type; } else { return new Cci.ModifiedTypeReference(type, ImmutableArray<Cci.ICustomModifier>.CastUp(customModifiers)); } } ImmutableArray<Cci.ICustomModifier> Cci.IFieldReference.RefCustomModifiers => ImmutableArray<Cci.ICustomModifier>.CastUp(AdaptedFieldSymbol.RefCustomModifiers); bool Cci.IFieldReference.IsByReference => AdaptedFieldSymbol.RefKind != RefKind.None; Cci.IFieldDefinition Cci.IFieldReference.GetResolvedField(EmitContext context) { return ResolvedFieldImpl((PEModuleBuilder)context.Module); } private Cci.IFieldDefinition ResolvedFieldImpl(PEModuleBuilder moduleBeingBuilt) { Debug.Assert(this.IsDefinitionOrDistinct()); if (AdaptedFieldSymbol.IsDefinition && AdaptedFieldSymbol.ContainingModule == moduleBeingBuilt.SourceModule) { return this; } return null; } Cci.ISpecializedFieldReference Cci.IFieldReference.AsSpecializedFieldReference { get { Debug.Assert(this.IsDefinitionOrDistinct()); if (!AdaptedFieldSymbol.IsDefinition) { return this; } return null; } } Cci.ITypeReference Cci.ITypeMemberReference.GetContainingType(EmitContext context) { PEModuleBuilder moduleBeingBuilt = (PEModuleBuilder)context.Module; Debug.Assert(this.IsDefinitionOrDistinct()); return moduleBeingBuilt.Translate(AdaptedFieldSymbol.ContainingType, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNode, diagnostics: context.Diagnostics, needDeclaration: AdaptedFieldSymbol.IsDefinition); } void Cci.IReference.Dispatch(Cci.MetadataVisitor visitor) { Debug.Assert(this.IsDefinitionOrDistinct()); if (!AdaptedFieldSymbol.IsDefinition) { visitor.Visit((Cci.ISpecializedFieldReference)this); } else if (AdaptedFieldSymbol.ContainingModule == ((PEModuleBuilder)visitor.Context.Module).SourceModule) { visitor.Visit((Cci.IFieldDefinition)this); } else { visitor.Visit((Cci.IFieldReference)this); } } Cci.IDefinition Cci.IReference.AsDefinition(EmitContext context) { PEModuleBuilder moduleBeingBuilt = (PEModuleBuilder)context.Module; return ResolvedFieldImpl(moduleBeingBuilt); } string Cci.INamedEntity.Name { get { return AdaptedFieldSymbol.MetadataName; } } bool Cci.IFieldReference.IsContextualNamedEntity { get { return false; } } MetadataConstant Cci.IFieldDefinition.GetCompileTimeValue(EmitContext context) { CheckDefinitionInvariant(); return GetMetadataConstantValue(context); } internal MetadataConstant GetMetadataConstantValue(EmitContext context) { // A constant field of type decimal is not treated as a compile time value in CLR, // so check if it is a metadata constant, not just a constant to exclude decimals. if (AdaptedFieldSymbol.IsMetadataConstant) { // NOTE: We would like to be able to assert that the constant value of this field // is not bad (i.e. ConstantValue.Bad) if it is being consumed by CCI, but we can't // because this method is called by the ReferenceIndexer in the metadata-only case // (and we specifically don't want to prevent metadata-only emit because of a bad // constant). If the constant value is bad, we'll end up exposing null to CCI. return ((PEModuleBuilder)context.Module).CreateConstant(AdaptedFieldSymbol.Type, AdaptedFieldSymbol.ConstantValue, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNode, diagnostics: context.Diagnostics); } return null; } ImmutableArray<byte> Cci.IFieldDefinition.MappedData { get { CheckDefinitionInvariant(); return default(ImmutableArray<byte>); } } bool Cci.IFieldDefinition.IsCompileTimeConstant { get { CheckDefinitionInvariant(); // A constant field of type decimal is not treated as a compile time value in CLR, // so check if it is a metadata constant, not just a constant to exclude decimals. return AdaptedFieldSymbol.IsMetadataConstant; } } bool Cci.IFieldDefinition.IsNotSerialized { get { CheckDefinitionInvariant(); return AdaptedFieldSymbol.IsNotSerialized; } } bool Cci.IFieldDefinition.IsReadOnly { get { CheckDefinitionInvariant(); return AdaptedFieldSymbol.IsReadOnly || (AdaptedFieldSymbol.IsConst && !AdaptedFieldSymbol.IsMetadataConstant); } } bool Cci.IFieldDefinition.IsRuntimeSpecial { get { CheckDefinitionInvariant(); return AdaptedFieldSymbol.HasRuntimeSpecialName; } } bool Cci.IFieldDefinition.IsSpecialName { get { CheckDefinitionInvariant(); return AdaptedFieldSymbol.HasSpecialName; } } bool Cci.IFieldDefinition.IsStatic { get { CheckDefinitionInvariant(); return AdaptedFieldSymbol.IsStatic; } } bool Cci.IFieldDefinition.IsMarshalledExplicitly { get { CheckDefinitionInvariant(); return AdaptedFieldSymbol.IsMarshalledExplicitly; } } Cci.IMarshallingInformation Cci.IFieldDefinition.MarshallingInformation { get { CheckDefinitionInvariant(); return AdaptedFieldSymbol.MarshallingInformation; } } ImmutableArray<byte> Cci.IFieldDefinition.MarshallingDescriptor { get { CheckDefinitionInvariant(); return AdaptedFieldSymbol.MarshallingDescriptor; } } int Cci.IFieldDefinition.Offset { get { CheckDefinitionInvariant(); return AdaptedFieldSymbol.TypeLayoutOffset ?? 0; } } Cci.ITypeDefinition Cci.ITypeDefinitionMember.ContainingTypeDefinition { get { CheckDefinitionInvariant(); return AdaptedFieldSymbol.ContainingType.GetCciAdapter(); } } Cci.TypeMemberVisibility Cci.ITypeDefinitionMember.Visibility { get { CheckDefinitionInvariant(); return AdaptedFieldSymbol.MetadataVisibility; } } Cci.IFieldReference Cci.ISpecializedFieldReference.UnspecializedVersion { get { Debug.Assert(!AdaptedFieldSymbol.IsDefinition); return AdaptedFieldSymbol.OriginalDefinition.GetCciAdapter(); } } } internal partial class FieldSymbol { #if DEBUG private FieldSymbolAdapter _lazyAdapter; protected sealed override SymbolAdapter GetCciAdapterImpl() => GetCciAdapter(); internal new FieldSymbolAdapter GetCciAdapter() { if (_lazyAdapter is null) { return InterlockedOperations.Initialize(ref _lazyAdapter, new FieldSymbolAdapter(this)); } return _lazyAdapter; } #else internal FieldSymbol AdaptedFieldSymbol => this; internal new FieldSymbol GetCciAdapter() { return this; } #endif internal virtual bool IsMarshalledExplicitly { get { CheckDefinitionInvariant(); return this.MarshallingInformation != null; } } internal virtual ImmutableArray<byte> MarshallingDescriptor { get { CheckDefinitionInvariant(); return default(ImmutableArray<byte>); } } } #if DEBUG internal partial class FieldSymbolAdapter { internal FieldSymbolAdapter(FieldSymbol underlyingFieldSymbol) { AdaptedFieldSymbol = underlyingFieldSymbol; } internal sealed override Symbol AdaptedSymbol => AdaptedFieldSymbol; internal FieldSymbol AdaptedFieldSymbol { get; } } #endif }