| File: ILCompiler\Metadata\Transform.Method.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.MetadataTransform\ILCompiler.MetadataTransform.csproj (ILCompiler.MetadataTransform) |
// 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 Internal.Metadata.NativeFormat.Writer; using Cts = Internal.TypeSystem; using Ecma = System.Reflection.Metadata; using Debug = System.Diagnostics.Debug; using MethodAttributes = System.Reflection.MethodAttributes; using MethodImplAttributes = System.Reflection.MethodImplAttributes; using SignatureCallingConvention = Internal.Metadata.NativeFormat.SignatureCallingConvention; namespace ILCompiler.Metadata { internal partial class Transform<TPolicy> { internal EntityMap<Cts.MethodDesc, MetadataRecord> _methods = new EntityMap<Cts.MethodDesc, MetadataRecord>(EqualityComparer<Cts.MethodDesc>.Default); private Action<Cts.MethodDesc, Method> _initMethodDef; private Action<Cts.MethodDesc, MemberReference> _initMethodRef; private Action<Cts.MethodDesc, MethodInstantiation> _initMethodInst; public override MetadataRecord HandleQualifiedMethod(Cts.MethodDesc method) { MetadataRecord rec; if (method is Cts.InstantiatedMethod) { rec = HandleMethodInstantiation(method); } else if (method.IsTypicalMethodDefinition && _policy.GeneratesMetadata(method)) { rec = new QualifiedMethod { EnclosingType = (TypeDefinition)HandleType(method.OwningType), Method = HandleMethodDefinition(method), }; } else { rec = HandleMethodReference(method); } Debug.Assert(rec is QualifiedMethod || rec is MemberReference || rec is MethodInstantiation); return rec; } private Method HandleMethodDefinition(Cts.MethodDesc method) { Debug.Assert(method.IsTypicalMethodDefinition); Debug.Assert(_policy.GeneratesMetadata(method)); return (Method)_methods.GetOrCreate(method, _initMethodDef ??= InitializeMethodDefinition); } private void InitializeMethodDefinition(Cts.MethodDesc entity, Method record) { record.Name = HandleString(entity.GetName()); if (entity.HasInstantiation) { record.GenericParameters.Capacity = entity.Instantiation.Length; foreach (var p in entity.Instantiation) record.GenericParameters.Add(HandleGenericParameter((Cts.GenericParameterDesc)p)); } var ecmaEntity = entity as Cts.Ecma.EcmaMethod; if (ecmaEntity != null) { Ecma.MetadataReader reader = ecmaEntity.MetadataReader; Ecma.MethodDefinition methodDef = reader.GetMethodDefinition(ecmaEntity.Handle); Ecma.ParameterHandleCollection paramHandles = methodDef.GetParameters(); Cts.MethodSignature sig = entity.Signature; record.Signature = sig.HasEmbeddedSignatureData ? HandleMethodSignature(ecmaEntity.Module, methodDef.Signature) : HandleMethodSignature(entity.Signature); record.Parameters.Capacity = paramHandles.Count; foreach (var paramHandle in paramHandles) { if (!_policy.GeneratesMetadata(ecmaEntity.Module, paramHandle)) continue; Ecma.Parameter param = reader.GetParameter(paramHandle); Parameter paramRecord = new Parameter { Flags = param.Attributes, Name = HandleString(reader.GetString(param.Name)), Sequence = checked((ushort)param.SequenceNumber) }; Ecma.ConstantHandle defaultValue = param.GetDefaultValue(); if (!defaultValue.IsNil) { paramRecord.DefaultValue = HandleConstant(ecmaEntity.Module, defaultValue); } Ecma.CustomAttributeHandleCollection paramAttributes = param.GetCustomAttributes(); if (paramAttributes.Count > 0) { paramRecord.CustomAttributes = HandleCustomAttributes(ecmaEntity.Module, paramAttributes); } record.Parameters.Add(paramRecord); } Ecma.CustomAttributeHandleCollection attributes = methodDef.GetCustomAttributes(); if (attributes.Count > 0) { record.CustomAttributes = HandleCustomAttributes(ecmaEntity.Module, attributes); } } else { throw new NotImplementedException(); } record.Flags = GetMethodAttributes(entity); record.ImplFlags = GetMethodImplAttributes(entity); //TODO: RVA } private MemberReference HandleMethodReference(Cts.MethodDesc method) { Debug.Assert(method.IsMethodDefinition); return (MemberReference)_methods.GetOrCreate(method, _initMethodRef ??= InitializeMethodReference); } private void InitializeMethodReference(Cts.MethodDesc entity, MemberReference record) { record.Name = HandleString(entity.GetName()); record.Parent = HandleType(entity.OwningType); record.Signature = HandleMethodSignature(entity.GetTypicalMethodDefinition().Signature); } private MethodInstantiation HandleMethodInstantiation(Cts.MethodDesc method) { return (MethodInstantiation)_methods.GetOrCreate(method, _initMethodInst ??= InitializeMethodInstantiation); } private void InitializeMethodInstantiation(Cts.MethodDesc entity, MethodInstantiation record) { Cts.InstantiatedMethod instantiation = (Cts.InstantiatedMethod)entity; record.Method = HandleQualifiedMethod(instantiation.GetMethodDefinition()); record.GenericTypeArguments.Capacity = instantiation.Instantiation.Length; foreach (Cts.TypeDesc typeArgument in instantiation.Instantiation) { record.GenericTypeArguments.Add(HandleType(typeArgument)); } } public override MethodSignature HandleMethodSignature(Cts.MethodSignature signature) { // TODO: if Cts.MethodSignature implements Equals/GetHashCode, we could enable pooling here. var result = new MethodSignature { CallingConvention = GetSignatureCallingConvention(signature), GenericParameterCount = signature.GenericParameterCount, ReturnType = HandleType(signature.ReturnType), // TODO-NICE: VarArgParameters }; result.Parameters.Capacity = signature.Length; for (int i = 0; i < signature.Length; i++) { result.Parameters.Add(HandleType(signature[i])); } return result; } private MethodSignature HandleMethodSignature(Cts.Ecma.EcmaModule module, Ecma.BlobHandle sigBlobHandle) { Ecma.BlobReader blobReader = module.MetadataReader.GetBlobReader(sigBlobHandle); return HandleMethodSignature(module, ref blobReader); } private MethodSignature HandleMethodSignature(Cts.Ecma.EcmaModule module, ref Ecma.BlobReader blobReader) { Ecma.SignatureHeader header = blobReader.ReadSignatureHeader(); int arity = header.IsGeneric ? blobReader.ReadCompressedInteger() : 0; int count = blobReader.ReadCompressedInteger(); var result = new MethodSignature { CallingConvention = GetSignatureCallingConvention(header), GenericParameterCount = arity, ReturnType = HandleType(module, ref blobReader), // TODO-NICE: VarArgParameters }; result.Parameters.Capacity = count; for (int i = 0; i < count; i++) { result.Parameters.Add(HandleType(module, ref blobReader)); } return result; } private static MethodAttributes GetMethodAttributes(Cts.MethodDesc method) { var ecmaMethod = method as Cts.Ecma.EcmaMethod; if (ecmaMethod != null) { Ecma.MetadataReader reader = ecmaMethod.MetadataReader; Ecma.MethodDefinition methodDef = reader.GetMethodDefinition(ecmaMethod.Handle); return methodDef.Attributes; } else throw new NotImplementedException(); } private static MethodImplAttributes GetMethodImplAttributes(Cts.MethodDesc method) { var ecmaMethod = method as Cts.Ecma.EcmaMethod; if (ecmaMethod != null) { Ecma.MetadataReader reader = ecmaMethod.MetadataReader; Ecma.MethodDefinition methodDef = reader.GetMethodDefinition(ecmaMethod.Handle); return methodDef.ImplAttributes; } else throw new NotImplementedException(); } private static SignatureCallingConvention GetSignatureCallingConvention(Cts.MethodSignature signature) { Debug.Assert((int)Cts.MethodSignatureFlags.UnmanagedCallingConventionCdecl == (int)SignatureCallingConvention.Cdecl); Debug.Assert((int)Cts.MethodSignatureFlags.UnmanagedCallingConventionThisCall == (int)SignatureCallingConvention.ThisCall); Debug.Assert((int)Cts.MethodSignatureFlags.UnmanagedCallingConventionMask == (int)SignatureCallingConvention.UnmanagedCallingConventionMask); SignatureCallingConvention callingConvention = (SignatureCallingConvention)(signature.Flags & Cts.MethodSignatureFlags.UnmanagedCallingConventionMask); if ((signature.Flags & Cts.MethodSignatureFlags.Static) == 0) { callingConvention |= SignatureCallingConvention.HasThis; } if ((signature.Flags & Cts.MethodSignatureFlags.ExplicitThis) != 0) { callingConvention |= SignatureCallingConvention.ExplicitThis; } return callingConvention; } private static SignatureCallingConvention GetSignatureCallingConvention(Ecma.SignatureHeader signature) { Debug.Assert((int)Ecma.SignatureCallingConvention.CDecl == (int)SignatureCallingConvention.Cdecl); Debug.Assert((int)Ecma.SignatureCallingConvention.ThisCall == (int)SignatureCallingConvention.ThisCall); Debug.Assert((int)Ecma.SignatureCallingConvention.Unmanaged == (int)SignatureCallingConvention.Unmanaged); SignatureCallingConvention callingConvention = (SignatureCallingConvention)(signature.CallingConvention); if (signature.IsInstance) { callingConvention |= SignatureCallingConvention.HasThis; } return callingConvention; } } }