| File: Emitter\Model\FunctionPointerTypeSymbolAdapter.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. using System.Collections.Generic; using System.Collections.Immutable; using System.Reflection.Metadata; using System.Threading; using Microsoft.Cci; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Symbols; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols { internal sealed partial class #if DEBUG FunctionPointerTypeSymbolAdapter : SymbolAdapter, #else FunctionPointerTypeSymbol : #endif IFunctionPointerTypeReference { private FunctionPointerMethodSignature? _lazySignature; ISignature IFunctionPointerTypeReference.Signature { get { if (_lazySignature is null) { Interlocked.CompareExchange(ref _lazySignature, new FunctionPointerMethodSignature(AdaptedFunctionPointerTypeSymbol.Signature), null); } return _lazySignature; } } void IReference.Dispatch(MetadataVisitor visitor) => visitor.Visit((IFunctionPointerTypeReference)this); bool ITypeReference.IsEnum => false; Cci.PrimitiveTypeCode ITypeReference.TypeCode => Cci.PrimitiveTypeCode.FunctionPointer; TypeDefinitionHandle ITypeReference.TypeDef => default; IGenericMethodParameterReference? ITypeReference.AsGenericMethodParameterReference => null; IGenericTypeInstanceReference? ITypeReference.AsGenericTypeInstanceReference => null; IGenericTypeParameterReference? ITypeReference.AsGenericTypeParameterReference => null; INamespaceTypeReference? ITypeReference.AsNamespaceTypeReference => null; INestedTypeReference? ITypeReference.AsNestedTypeReference => null; ISpecializedNestedTypeReference? ITypeReference.AsSpecializedNestedTypeReference => null; INamespaceTypeDefinition? ITypeReference.AsNamespaceTypeDefinition(EmitContext context) => null; INestedTypeDefinition? ITypeReference.AsNestedTypeDefinition(EmitContext context) => null; ITypeDefinition? ITypeReference.AsTypeDefinition(EmitContext context) => null; ITypeDefinition? ITypeReference.GetResolvedType(EmitContext context) => null; bool ITypeReference.IsValueType => AdaptedFunctionPointerTypeSymbol.IsValueType; IEnumerable<ICustomAttribute> IReference.GetAttributes(EmitContext context) => SpecializedCollections.EmptyEnumerable<ICustomAttribute>(); IDefinition? IReference.AsDefinition(EmitContext context) => null; /// <summary> /// We need to be able to differentiate between a FunctionPointer used as a type and a function pointer used /// as a StandaloneMethodSig. To do this, we wrap the <see cref="FunctionPointerMethodSymbol"/> in a /// <see cref="FunctionPointerMethodSignature"/>, to hide its implementation of <see cref="IMethodSymbol"/>. /// </summary> private sealed class FunctionPointerMethodSignature : ISignature { private readonly FunctionPointerMethodSymbol _underlying; internal ISignature Underlying => _underlying.GetCciAdapter(); internal FunctionPointerMethodSignature(FunctionPointerMethodSymbol underlying) { _underlying = underlying; } public CallingConvention CallingConvention => Underlying.CallingConvention; public ushort ParameterCount => Underlying.ParameterCount; public ImmutableArray<ICustomModifier> ReturnValueCustomModifiers => Underlying.ReturnValueCustomModifiers; public ImmutableArray<ICustomModifier> RefCustomModifiers => Underlying.RefCustomModifiers; public bool ReturnValueIsByRef => Underlying.ReturnValueIsByRef; public ImmutableArray<IParameterTypeInformation> GetParameters(EmitContext context) => Underlying.GetParameters(context); public ITypeReference GetType(EmitContext context) => Underlying.GetType(context); public override bool Equals(object? obj) { // It is not supported to rely on default equality of these Cci objects, an explicit way to compare and hash them should be used. throw ExceptionUtilities.Unreachable(); } // It is not supported to rely on default equality of these Cci objects, an explicit way to compare and hash them should be used. public override int GetHashCode() => throw ExceptionUtilities.Unreachable(); public override string ToString() => _underlying.ToDisplayString(SymbolDisplayFormat.ILVisualizationFormat); } } internal partial class FunctionPointerTypeSymbol { #if DEBUG private FunctionPointerTypeSymbolAdapter? _lazyAdapter; protected sealed override SymbolAdapter GetCciAdapterImpl() => GetCciAdapter(); internal new FunctionPointerTypeSymbolAdapter GetCciAdapter() { if (_lazyAdapter is null) { return InterlockedOperations.Initialize(ref _lazyAdapter, new FunctionPointerTypeSymbolAdapter(this)); } return _lazyAdapter; } #else internal FunctionPointerTypeSymbol AdaptedFunctionPointerTypeSymbol => this; internal new FunctionPointerTypeSymbol GetCciAdapter() { return this; } #endif } #if DEBUG internal partial class FunctionPointerTypeSymbolAdapter { internal FunctionPointerTypeSymbolAdapter(FunctionPointerTypeSymbol underlyingFunctionPointerTypeSymbol) { AdaptedFunctionPointerTypeSymbol = underlyingFunctionPointerTypeSymbol; } internal sealed override Symbol AdaptedSymbol => AdaptedFunctionPointerTypeSymbol; internal FunctionPointerTypeSymbol AdaptedFunctionPointerTypeSymbol { get; } } #endif }