| File: System\Reflection\TypeLoading\MethodBase\Ecma\EcmaMethodDecoder.cs | Web Access |
| Project: src\runtime\src\libraries\System.Reflection.MetadataLoadContext\src\System.Reflection.MetadataLoadContext.csproj (System.Reflection.MetadataLoadContext) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Diagnostics; using System.Reflection.Metadata; using System.Runtime.InteropServices; namespace System.Reflection.TypeLoading.Ecma { internal readonly struct EcmaMethodDecoder : IMethodDecoder { private readonly MethodDefinitionHandle _handle; private readonly EcmaModule _module; internal EcmaMethodDecoder(MethodDefinitionHandle handle, EcmaModule module) : this() { _handle = handle; _module = module; _neverAccessThisExceptThroughMethodDefinitionProperty = handle.GetMethodDefinition(Reader); } public RoModule GetRoModule() => _module; public string ComputeName() => MethodDefinition.Name.GetString(Reader); public int MetadataToken => _handle.GetToken(); public IEnumerable<CustomAttributeData> ComputeTrueCustomAttributes() => MethodDefinition.GetCustomAttributes().ToTrueCustomAttributes(_module); public int ComputeGenericParameterCount() => MethodDefinition.GetGenericParameters().Count; public RoType[] ComputeGenericArgumentsOrParameters() { GenericParameterHandleCollection gphs = MethodDefinition.GetGenericParameters(); int count = gphs.Count; if (count == 0) return Array.Empty<RoType>(); RoType[] gps = new RoType[count]; foreach (GenericParameterHandle gph in gphs) { RoType gp = gph.ResolveGenericParameter(_module); gps[gp.GenericParameterPosition] = gp; } return gps; } public MethodAttributes ComputeAttributes() => MethodDefinition.Attributes; public CallingConventions ComputeCallingConvention() { BlobReader signatureBlob = MethodDefinition.Signature.GetBlobReader(Reader); SignatureHeader sigHeader = signatureBlob.ReadSignatureHeader(); CallingConventions result; if (sigHeader.CallingConvention == SignatureCallingConvention.VarArgs) result = CallingConventions.VarArgs; else result = CallingConventions.Standard; if (sigHeader.IsInstance) result |= CallingConventions.HasThis; if (sigHeader.HasExplicitThis) result |= CallingConventions.ExplicitThis; return result; } public MethodImplAttributes ComputeMethodImplementationFlags() => MethodDefinition.ImplAttributes; public MethodSig<RoParameter> SpecializeMethodSig(IRoMethodBase roMethodBase) { MetadataReader reader = Reader; MethodDefinition methodDefinition = MethodDefinition; MethodSignature<RoType> sig = methodDefinition.DecodeSignature(_module, roMethodBase.TypeContext); int numParameters = sig.RequiredParameterCount; MethodSig<RoParameter> methodSig = new MethodSig<RoParameter>(numParameters); foreach (ParameterHandle ph in methodDefinition.GetParameters()) { Parameter p = ph.GetParameter(reader); int position = p.SequenceNumber - 1; Type parameterType = position == -1 ? sig.ReturnType : sig.ParameterTypes[position]; methodSig[position] = new EcmaFatMethodParameter(roMethodBase, position, parameterType, ph); } for (int position = -1; position < numParameters; position++) { Type parameterType = position == -1 ? sig.ReturnType : sig.ParameterTypes[position]; methodSig[position] ??= new RoThinMethodParameter(roMethodBase, position, parameterType); } return methodSig; } public MethodSig<string> SpecializeMethodSigStrings(in TypeContext typeContext) { ISignatureTypeProvider<string, TypeContext> typeProvider = EcmaSignatureTypeProviderForToString.Instance; MethodSignature<string> sig = MethodDefinition.DecodeSignature(typeProvider, typeContext); int parameterCount = sig.ParameterTypes.Length; MethodSig<string> results = new MethodSig<string>(parameterCount); results[-1] = sig.ReturnType; for (int position = 0; position < parameterCount; position++) { results[position] = sig.ParameterTypes[position]; } return results; } public MethodBody? SpecializeMethodBody(IRoMethodBase owner) { int rva = MethodDefinition.RelativeVirtualAddress; if (rva == 0) return null; return new EcmaMethodBody(owner, ((EcmaModule)(owner.MethodBase.Module)).PEReader.GetMethodBody(rva)); } public DllImportAttribute ComputeDllImportAttribute() { MetadataReader reader = Reader; MethodImport mi = MethodDefinition.GetImport(); string libraryName = mi.Module.GetModuleReference(reader).Name.GetString(reader); string entryPointName = mi.Name.GetString(reader); MethodImportAttributes a = mi.Attributes; CharSet charSet = (a & MethodImportAttributes.CharSetMask) switch { MethodImportAttributes.CharSetAnsi => CharSet.Ansi, MethodImportAttributes.CharSetAuto => CharSet.Auto, MethodImportAttributes.CharSetUnicode => CharSet.Unicode, _ => CharSet.None, // Note: CharSet.None is actually the typical case, not an error case. }; CallingConvention callConv = (a & MethodImportAttributes.CallingConventionMask) switch { MethodImportAttributes.CallingConventionCDecl => CallingConvention.Cdecl, MethodImportAttributes.CallingConventionFastCall => CallingConvention.FastCall, MethodImportAttributes.CallingConventionStdCall => CallingConvention.StdCall, MethodImportAttributes.CallingConventionThisCall => CallingConvention.ThisCall, MethodImportAttributes.CallingConventionWinApi => CallingConvention.Winapi, _ => throw new BadImageFormatException(), }; return new DllImportAttribute(libraryName) { EntryPoint = entryPointName, ExactSpelling = (a & MethodImportAttributes.ExactSpelling) != 0, CharSet = charSet, CallingConvention = callConv, PreserveSig = (ComputeMethodImplementationFlags() & MethodImplAttributes.PreserveSig) != 0, SetLastError = (a & MethodImportAttributes.SetLastError) != 0, BestFitMapping = (a & MethodImportAttributes.BestFitMappingMask) == MethodImportAttributes.BestFitMappingEnable, ThrowOnUnmappableChar = (a & MethodImportAttributes.ThrowOnUnmappableCharMask) == MethodImportAttributes.ThrowOnUnmappableCharEnable, }; } private MetadataReader Reader => _module.Reader; private MetadataLoadContext Loader => GetRoModule().Loader; private MethodDefinition MethodDefinition { get { Loader.DisposeCheck(); return _neverAccessThisExceptThroughMethodDefinitionProperty; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] // Block from debugger watch windows so they don't AV the debugged process. private readonly MethodDefinition _neverAccessThisExceptThroughMethodDefinitionProperty; } }