public void TestFunctionPointerSignatures() { var ilModule = _context.GetModuleForSimpleName("ILMetadataAssembly"); Cts.MetadataType typeWithFunctionPointers = ilModule.GetType("SampleMetadata", "TypeWithFunctionPointers"); var policy = new SingleFileMetadataPolicy(); var transformResult = MetadataTransform.Run(policy, new[] { _systemModule, ilModule }); var typeWithFunctionPointersType = transformResult.GetTransformedTypeDefinition(typeWithFunctionPointers); var objectType = transformResult.GetTransformedTypeDefinition((Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.Object)); Assert.Equal(1, typeWithFunctionPointersType.Fields.Count); var theField = typeWithFunctionPointersType.Fields[0]; Assert.IsType <TypeSpecification>(theField.Signature.Type); var theFieldSignature = (TypeSpecification)theField.Signature.Type; Assert.IsType <FunctionPointerSignature>(theFieldSignature.Signature); var theFieldPointerSignature = (FunctionPointerSignature)theFieldSignature.Signature; Assert.Equal(objectType, theFieldPointerSignature.Signature.ReturnType); Assert.Equal(1, theFieldPointerSignature.Signature.Parameters.Count); Assert.Equal(objectType, theFieldPointerSignature.Signature.Parameters[0]); }
public void TestMultifileSanity() { var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly"); var policy = new MultifileMetadataPolicy(sampleMetadataModule); var transformResult = MetadataTransform.Run(policy, new[] { _systemModule, sampleMetadataModule }); Assert.Equal(1, transformResult.Scopes.Count); var sampleScope = transformResult.Scopes.Single(); Assert.Equal(sampleMetadataModule.GetAllTypes().Count(t => !policy.IsBlocked(t)), sampleScope.GetAllTypes().Count()); var objectType = (Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.Object); var objectRecord = transformResult.GetTransformedTypeReference(objectType); Assert.Equal("Object", objectRecord.TypeName.Value); var stringType = (Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.String); var stringRecord = transformResult.GetTransformedTypeReference(stringType); Assert.Equal("String", stringRecord.TypeName.Value); Assert.Same(objectRecord.ParentNamespaceOrType, stringRecord.ParentNamespaceOrType); Assert.IsType <NamespaceReference>(objectRecord.ParentNamespaceOrType); var parentNamespace = objectRecord.ParentNamespaceOrType as NamespaceReference; Assert.Equal("System", parentNamespace.Name.Value); Assert.Null(transformResult.GetTransformedTypeDefinition(objectType)); Assert.Null(transformResult.GetTransformedTypeDefinition(stringType)); }
public void TestExplicitScopeAttributesForWinRTSingleFilePolicy() { // Test that custom attributes referring to blocked types don't show up in metadata var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly"); var sampleWinRTMetadataModule = _context.GetModuleForSimpleName("SampleWinRTMetadataAssembly"); var windowsWinRTMetadataModule = _context.GetModuleForSimpleName("WindowsWinRTMetadataAssembly"); Cts.MetadataType controlType = windowsWinRTMetadataModule.GetType("Windows", "Control"); Cts.MetadataType derivedFromControl = sampleWinRTMetadataModule.GetType("SampleMetadataWinRT", "DerivedFromControl"); Cts.MetadataType derivedFromControlInCustomScope = sampleWinRTMetadataModule.GetType("SampleMetadataWinRT", "DerivedFromControlAndInCustomScope"); var policy = new SingleFileMetadataPolicy(); var transformResult = MetadataTransform.Run(policy, new[] { _systemModule, sampleMetadataModule, sampleWinRTMetadataModule, windowsWinRTMetadataModule }); var controlTypeMetadata = transformResult.GetTransformedTypeDefinition(controlType); var derivedFromControlMetadata = transformResult.GetTransformedTypeDefinition(derivedFromControl); var derivedFromControlInCustomScopeMetadata = transformResult.GetTransformedTypeDefinition(derivedFromControlInCustomScope); CheckTypeDefinitionForProperWinRTHome(controlTypeMetadata, "Windows"); ScopeDefinition scopeDefOfDerivedFromControlType = GetScopeDefinitionOfType(derivedFromControlMetadata); Assert.Equal("SampleWinRTMetadataAssembly", scopeDefOfDerivedFromControlType.Name.Value); CheckTypeDefinitionForProperWinRTHome(derivedFromControlInCustomScopeMetadata, "SampleMetadataWinRT"); }
public void TestAllTypes() { var policy = new SingleFileMetadataPolicy(); var transformResult = MetadataTransform.Run(policy, new[] { _systemModule }); Assert.Equal(1, transformResult.Scopes.Count()); Assert.Equal( _systemModule.GetAllTypes().Count(x => !policy.IsBlocked(x)), transformResult.Scopes.Single().GetAllTypes().Count()); }
protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List <MetadataMapping <MetadataType> > typeMappings, out List <MetadataMapping <MethodDesc> > methodMappings, out List <MetadataMapping <FieldDesc> > fieldMappings, out List <MetadataMapping <MethodDesc> > stackTraceMapping) { var ms = new MemoryStream(); var writer = new MetadataWriter(); // Run an empty transform pass. This doesn't matter. We just need an instance of the MetadataTransform. var transformed = MetadataTransform.Run(new Policy(), Array.Empty <ModuleDesc>()); MetadataTransform transform = transformed.Transform; // Generate entries in the blob for methods that will be necessary for stack trace purposes. var stackTraceRecords = new List <KeyValuePair <MethodDesc, MetadataRecord> >(); foreach (var methodBody in GetCompiledMethodBodies()) { MethodDesc method = methodBody.Method; MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); if (!_stackTraceEmissionPolicy.ShouldIncludeMethod(method)) { continue; } MetadataRecord record = CreateStackTraceRecord(transform, method); stackTraceRecords.Add(new KeyValuePair <MethodDesc, MetadataRecord>( method, record)); writer.AdditionalRootRecords.Add(record); } writer.Write(ms); metadataBlob = ms.ToArray(); typeMappings = new List <MetadataMapping <MetadataType> >(); methodMappings = new List <MetadataMapping <MethodDesc> >(); fieldMappings = new List <MetadataMapping <FieldDesc> >(); stackTraceMapping = new List <MetadataMapping <MethodDesc> >(); // Generate stack trace metadata mapping foreach (var stackTraceRecord in stackTraceRecords) { stackTraceMapping.Add(new MetadataMapping <MethodDesc>(stackTraceRecord.Key, writer.GetRecordHandle(stackTraceRecord.Value))); } }
private void EnsureMetadataGenerated() { if (_metadataBlob != null) { return; } var transformed = MetadataTransform.Run(new DummyMetadataPolicy(this), _modulesSeen); // TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate // TypeReference records for _typeDefinitionsGenerated that don't have metadata. // (To be used in MissingMetadataException messages) // Generate metadata blob var writer = new MetadataWriter(); writer.ScopeDefinitions.AddRange(transformed.Scopes); var ms = new MemoryStream(); writer.Write(ms); _metadataBlob = ms.ToArray(); // Generate type definition mappings foreach (var definition in _typeDefinitionsGenerated) { MetadataRecord record = transformed.GetTransformedTypeDefinition(definition); // Reflection requires that we maintain type identity. Even if we only generated a TypeReference record, // if there is an EEType for it, we also need a mapping table entry for it. if (record == null) { record = transformed.GetTransformedTypeReference(definition); } if (record != null) { _typeMappings.Add(new MetadataMapping <MetadataType>(definition, writer.GetRecordHandle(record))); } } foreach (var method in _methodsGenerated) { MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition()); if (record != null) { _methodMappings.Add(new MetadataMapping <MethodDesc>(method, writer.GetRecordHandle(record))); } } }
public void TestMethodImplMetadata() { // Test that custom attributes referring to blocked types don't show up in metadata var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly"); Cts.MetadataType iCloneable = sampleMetadataModule.GetType("SampleMetadataMethodImpl", "ICloneable"); Cts.MetadataType implementsICloneable = sampleMetadataModule.GetType("SampleMetadataMethodImpl", "ImplementsICloneable"); Cts.MethodDesc iCloneableDotClone = iCloneable.GetMethod("Clone", null); Cts.MethodDesc iCloneableImplementation = implementsICloneable.GetMethod("SampleMetadataMethodImpl.ICloneable.Clone", null); Cts.MethodDesc iCloneableDotGenericClone = iCloneable.GetMethod("GenericClone", null); Cts.MethodDesc iCloneableGenericImplementation = implementsICloneable.GetMethod("SampleMetadataMethodImpl.ICloneable.GenericClone", null); var policy = new SingleFileMetadataPolicy(); var transformResult = MetadataTransform.Run(policy, new[] { _systemModule, sampleMetadataModule }); var iCloneableType = transformResult.GetTransformedTypeDefinition(iCloneable); var implementsICloneableType = transformResult.GetTransformedTypeDefinition(implementsICloneable); Assert.Equal(2, implementsICloneableType.MethodImpls.Count); // non-generic MethodImpl Method iCloneableDotCloneMethod = transformResult.GetTransformedMethodDefinition(iCloneableDotClone); Method iCloneableImplementationMethod = transformResult.GetTransformedMethodDefinition(iCloneableImplementation); QualifiedMethod methodImplMethodDecl = (QualifiedMethod)implementsICloneableType.MethodImpls[0].MethodDeclaration; QualifiedMethod methodImplMethodBody = (QualifiedMethod)implementsICloneableType.MethodImpls[0].MethodBody; Assert.Equal(iCloneableDotCloneMethod, methodImplMethodDecl.Method); Assert.Equal(iCloneableType, methodImplMethodDecl.EnclosingType); Assert.Equal(iCloneableImplementationMethod, methodImplMethodBody.Method); Assert.Equal(implementsICloneableType, methodImplMethodBody.EnclosingType); // generic MethodImpl Method iCloneableDotGenericCloneMethod = transformResult.GetTransformedMethodDefinition(iCloneableDotGenericClone); Method iCloneableGenericImplementationMethod = transformResult.GetTransformedMethodDefinition(iCloneableGenericImplementation); QualifiedMethod methodImplGenericMethodDecl = (QualifiedMethod)implementsICloneableType.MethodImpls[1].MethodDeclaration; QualifiedMethod methodImplGenericMethodBody = (QualifiedMethod)implementsICloneableType.MethodImpls[1].MethodBody; Assert.Equal(iCloneableDotGenericCloneMethod, methodImplGenericMethodDecl.Method); Assert.Equal(iCloneableType, methodImplGenericMethodDecl.EnclosingType); Assert.Equal(iCloneableGenericImplementationMethod, methodImplGenericMethodBody.Method); Assert.Equal(implementsICloneableType, methodImplGenericMethodBody.EnclosingType); }
public void TestSampleMetadataGeneration() { var policy = new SingleFileMetadataPolicy(); var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly"); var transformResult = MetadataTransform.Run(policy, new[] { _systemModule, sampleMetadataModule }); Assert.Equal(2, transformResult.Scopes.Count); var systemScope = transformResult.Scopes.Single(s => s.Name.Value == "PrimaryMetadataAssembly"); var sampleScope = transformResult.Scopes.Single(s => s.Name.Value == "SampleMetadataAssembly"); Assert.Equal(_systemModule.GetAllTypes().Count(t => !policy.IsBlocked(t)), systemScope.GetAllTypes().Count()); Assert.Equal(sampleMetadataModule.GetAllTypes().Count(t => !policy.IsBlocked(t)), sampleScope.GetAllTypes().Count()); // TODO: check individual types }
public void TestStandaloneSignatureGeneration() { var transformResult = MetadataTransform.Run(new SingleFileMetadataPolicy(), new[] { _systemModule }); var stringRecord = transformResult.GetTransformedTypeDefinition( (Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.String)); var singleRecord = transformResult.GetTransformedTypeDefinition( (Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.Single)); var sig = new Cts.MethodSignature( 0, 0, _context.GetWellKnownType(Cts.WellKnownType.String), new[] { _context.GetWellKnownType(Cts.WellKnownType.Single) }); var sigRecord = transformResult.Transform.HandleMethodSignature(sig); // Verify the signature is connected to the existing transformResult world Assert.Same(stringRecord, sigRecord.ReturnType); Assert.Equal(1, sigRecord.Parameters.Count); Assert.Same(singleRecord, sigRecord.Parameters[0]); }
public void TestBlockedInterface() { // BlockedObject implements IBlockedInterface, which is a metadata blocked type and should not show // up in the BlockedObject interface list. var policy = new SingleFileMetadataPolicy(); var transformResult = MetadataTransform.Run(policy, new[] { _systemModule }); Cts.MetadataType iblockedinterface = _systemModule.GetType("System.Private.CompilerServices", "IBlockedInterface"); Cts.MetadataType comObject = _systemModule.GetType("System", "BlockedObject"); Assert.Equal(1, comObject.ExplicitlyImplementedInterfaces.Length); Assert.Equal(iblockedinterface, comObject.ExplicitlyImplementedInterfaces[0]); Assert.Null(transformResult.GetTransformedTypeDefinition(iblockedinterface)); Assert.Null(transformResult.GetTransformedTypeReference(iblockedinterface)); TypeDefinition comObjectRecord = transformResult.GetTransformedTypeDefinition(comObject); Assert.NotNull(comObjectRecord); Assert.Equal(comObject.Name, comObjectRecord.Name.Value); Assert.Equal(0, comObjectRecord.Interfaces.Count); }
public void TestNestedTypeReference() { // A type reference nested under a type that has a definition record. The transform is required // to create a type reference for the containing type because a type *definition* can't be a parent // to a type *reference*. var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly"); Cts.MetadataType genericOutside = sampleMetadataModule.GetType("SampleMetadata", "GenericOutside`1"); Cts.MetadataType inside = genericOutside.GetNestedType("Inside"); { MockPolicy policy = new MockPolicy( type => { return(type == genericOutside); }); var result = MetadataTransform.Run(policy, new[] { sampleMetadataModule }); Assert.Equal(1, result.Scopes.Count); Assert.Equal(1, result.Scopes.Single().GetAllTypes().Count()); var genericOutsideDefRecord = result.GetTransformedTypeDefinition(genericOutside); Assert.NotNull(genericOutsideDefRecord); Assert.Null(result.GetTransformedTypeReference(inside)); var insideRecord = result.Transform.HandleType(inside); Assert.IsType <TypeReference>(insideRecord); var genericOutsideRefRecord = ((TypeReference)insideRecord).ParentNamespaceOrType as TypeReference; Assert.NotNull(genericOutsideRefRecord); Assert.Equal(genericOutside.Name, genericOutsideRefRecord.TypeName.Value); Assert.Same(genericOutsideDefRecord, result.GetTransformedTypeDefinition(genericOutside)); } }
public void TestBlockedAttributes() { // Test that custom attributes referring to blocked types don't show up in metadata var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly"); Cts.MetadataType attributeHolder = sampleMetadataModule.GetType("BlockedMetadata", "AttributeHolder"); var policy = new SingleFileMetadataPolicy(); var transformResult = MetadataTransform.Run(policy, new[] { _systemModule, sampleMetadataModule }); int blockedCount = 0; int allowedCount = 0; foreach (var field in attributeHolder.GetFields()) { var transformedRecord = transformResult.GetTransformedFieldDefinition(field); Assert.NotNull(transformedRecord); if (field.Name.StartsWith("Blocked")) { blockedCount++; Assert.Equal(0, transformedRecord.CustomAttributes.Count); } else { allowedCount++; Assert.StartsWith("Allowed", field.Name); Assert.Equal(1, transformedRecord.CustomAttributes.Count); } } Assert.Equal(5, allowedCount); Assert.Equal(8, blockedCount); }
protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List <MetadataMapping <MetadataType> > typeMappings, out List <MetadataMapping <MethodDesc> > methodMappings, out List <MetadataMapping <FieldDesc> > fieldMappings) { foreach (var type in factory.MetadataManager.GetTypesWithEETypes()) { var definition = type.GetTypeDefinition() as Internal.TypeSystem.Ecma.EcmaType; if (definition == null) { continue; } if (factory.CompilationModuleGroup.ContainsType(definition)) { _typeDefinitionsToGenerate.Add(definition); _modulesSeen.Add(definition.Module); } } foreach (var method in GetCompiledMethods()) { var typicalMethod = method.GetTypicalMethodDefinition() as Internal.TypeSystem.Ecma.EcmaMethod; if (typicalMethod != null) { var owningType = (MetadataType)typicalMethod.OwningType; if (factory.CompilationModuleGroup.ContainsType(owningType)) { _typeDefinitionsToGenerate.Add(owningType); _modulesSeen.Add(owningType.Module); _methodDefinitionsToGenerate.Add(typicalMethod); } } } var transformed = MetadataTransform.Run(new GeneratedTypesAndCodeMetadataPolicy(this), _modulesSeen); // TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate // TypeReference records for _typeDefinitionsGenerated that don't have metadata. // (To be used in MissingMetadataException messages) // Generate metadata blob var writer = new MetadataWriter(); writer.ScopeDefinitions.AddRange(transformed.Scopes); var ms = new MemoryStream(); // .NET metadata is UTF-16 and UTF-16 contains code points that don't translate to UTF-8. var noThrowUtf8Encoding = new UTF8Encoding(false, false); using (var logWriter = _metadataLogFile != null ? new StreamWriter(File.Open(_metadataLogFile, FileMode.Create, FileAccess.Write, FileShare.Read), noThrowUtf8Encoding) : null) { writer.LogWriter = logWriter; writer.Write(ms); } metadataBlob = ms.ToArray(); typeMappings = new List <MetadataMapping <MetadataType> >(); methodMappings = new List <MetadataMapping <MethodDesc> >(); fieldMappings = new List <MetadataMapping <FieldDesc> >(); // Generate type definition mappings foreach (var type in factory.MetadataManager.GetTypesWithEETypes()) { MetadataType definition = type.IsTypeDefinition ? type as MetadataType : null; if (definition == null) { continue; } MetadataRecord record = transformed.GetTransformedTypeDefinition(definition); // Reflection requires that we maintain type identity. Even if we only generated a TypeReference record, // if there is an EEType for it, we also need a mapping table entry for it. if (record == null) { record = transformed.GetTransformedTypeReference(definition); } if (record != null) { typeMappings.Add(new MetadataMapping <MetadataType>(definition, writer.GetRecordHandle(record))); } } foreach (var method in GetCompiledMethods()) { if (method.IsCanonicalMethod(CanonicalFormKind.Specific)) { // Canonical methods are not interesting. continue; } MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition()); if (record != null) { methodMappings.Add(new MetadataMapping <MethodDesc>(method, writer.GetRecordHandle(record))); } } foreach (var eetypeGenerated in GetTypesWithEETypes()) { if (eetypeGenerated.IsGenericDefinition) { continue; } if (eetypeGenerated.HasInstantiation) { // Collapsing of field map entries based on canonicalization, to avoid redundant equivalent entries TypeDesc canonicalType = eetypeGenerated.ConvertToCanonForm(CanonicalFormKind.Specific); if (canonicalType != eetypeGenerated && TypeGeneratesEEType(canonicalType)) { continue; } } foreach (FieldDesc field in eetypeGenerated.GetFields()) { Field record = transformed.GetTransformedFieldDefinition(field.GetTypicalFieldDefinition()); if (record != null) { fieldMappings.Add(new MetadataMapping <FieldDesc>(field, writer.GetRecordHandle(record))); } } } }
private List <MetadataMapping <MethodDesc> > GenerateStackTraceMetadata(NodeFactory factory) { var transformed = MetadataTransform.Run(new NoDefinitionMetadataPolicy(), Array.Empty <ModuleDesc>()); MetadataTransform transform = transformed.Transform; // Generate metadata blob var writer = new MetadataWriter(); // Only emit stack trace metadata for those methods which don't have reflection metadata HashSet <MethodDesc> methodInvokeMap = new HashSet <MethodDesc>(); foreach (var mappingEntry in GetMethodMapping(factory)) { var method = mappingEntry.Entity; if (ShouldMethodBeInInvokeMap(method)) { methodInvokeMap.Add(method); } } // Generate entries in the blob for methods that will be necessary for stack trace purposes. var stackTraceRecords = new List <KeyValuePair <MethodDesc, MetadataRecord> >(); foreach (var methodBody in GetCompiledMethodBodies()) { NonExternMethodSymbolNode methodNode = methodBody as NonExternMethodSymbolNode; if (methodNode != null && !methodNode.HasCompiledBody) { continue; } MethodDesc method = methodBody.Method; if (methodInvokeMap.Contains(method)) { continue; } if (!_stackTraceEmissionPolicy.ShouldIncludeMethod(method)) { continue; } MetadataRecord record = CreateStackTraceRecord(transform, method); stackTraceRecords.Add(new KeyValuePair <MethodDesc, MetadataRecord>( method, record)); writer.AdditionalRootRecords.Add(record); } var ms = new MemoryStream(); writer.Write(ms); _stackTraceBlob = ms.ToArray(); var result = new List <MetadataMapping <MethodDesc> >(); // Generate stack trace metadata mapping foreach (var stackTraceRecord in stackTraceRecords) { result.Add(new MetadataMapping <MethodDesc>(stackTraceRecord.Key, writer.GetRecordHandle(stackTraceRecord.Value))); } return(result); }
protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List <MetadataMapping <MetadataType> > typeMappings, out List <MetadataMapping <MethodDesc> > methodMappings, out List <MetadataMapping <FieldDesc> > fieldMappings) { var transformed = MetadataTransform.Run(new GeneratedTypesAndCodeMetadataPolicy(this), _modulesSeen); // TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate // TypeReference records for _typeDefinitionsGenerated that don't have metadata. // (To be used in MissingMetadataException messages) // Generate metadata blob var writer = new MetadataWriter(); writer.ScopeDefinitions.AddRange(transformed.Scopes); var ms = new MemoryStream(); writer.Write(ms); metadataBlob = ms.ToArray(); typeMappings = new List <MetadataMapping <MetadataType> >(); methodMappings = new List <MetadataMapping <MethodDesc> >(); fieldMappings = new List <MetadataMapping <FieldDesc> >(); // Generate type definition mappings foreach (var definition in _typeDefinitionsGenerated) { MetadataRecord record = transformed.GetTransformedTypeDefinition(definition); // Reflection requires that we maintain type identity. Even if we only generated a TypeReference record, // if there is an EEType for it, we also need a mapping table entry for it. if (record == null) { record = transformed.GetTransformedTypeReference(definition); } if (record != null) { typeMappings.Add(new MetadataMapping <MetadataType>(definition, writer.GetRecordHandle(record))); } } foreach (var method in GetCompiledMethods()) { if (method.IsCanonicalMethod(CanonicalFormKind.Specific)) { // Canonical methods are not interesting. continue; } MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition()); if (record != null) { methodMappings.Add(new MetadataMapping <MethodDesc>(method, writer.GetRecordHandle(record))); } } foreach (var eetypeGenerated in GetTypesWithEETypes()) { if (eetypeGenerated.IsGenericDefinition) { continue; } if (eetypeGenerated.HasInstantiation) { // Collapsing of field map entries based on canonicalization, to avoid redundant equivalent entries TypeDesc canonicalType = eetypeGenerated.ConvertToCanonForm(CanonicalFormKind.Specific); if (canonicalType != eetypeGenerated && TypeGeneratesEEType(canonicalType)) { continue; } } foreach (FieldDesc field in eetypeGenerated.GetFields()) { Field record = transformed.GetTransformedFieldDefinition(field.GetTypicalFieldDefinition()); if (record != null) { fieldMappings.Add(new MetadataMapping <FieldDesc>(field, writer.GetRecordHandle(record))); } } } }
protected void ComputeMetadata <TPolicy>( TPolicy policy, NodeFactory factory, out byte[] metadataBlob, out List <MetadataMapping <MetadataType> > typeMappings, out List <MetadataMapping <MethodDesc> > methodMappings, out List <MetadataMapping <FieldDesc> > fieldMappings, out List <MetadataMapping <MethodDesc> > stackTraceMapping) where TPolicy : struct, IMetadataPolicy { var transformed = MetadataTransform.Run(policy, GetCompilationModulesWithMetadata()); MetadataTransform transform = transformed.Transform; // TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate // TypeReference records for _typeDefinitionsGenerated that don't have metadata. // (To be used in MissingMetadataException messages) // Generate metadata blob var writer = new MetadataWriter(); writer.ScopeDefinitions.AddRange(transformed.Scopes); // Generate entries in the blob for methods that will be necessary for stack trace purposes. var stackTraceRecords = new List <KeyValuePair <MethodDesc, MetadataRecord> >(); foreach (var methodBody in GetCompiledMethodBodies()) { MethodDesc method = methodBody.Method; MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); // Methods that will end up in the reflection invoke table should not have an entry in stack trace table // We'll try looking them up in reflection data at runtime. if (transformed.GetTransformedMethodDefinition(typicalMethod) != null && ShouldMethodBeInInvokeMap(method) && (GetMetadataCategory(method) & MetadataCategory.RuntimeMapping) != 0) { continue; } if (!_stackTraceEmissionPolicy.ShouldIncludeMethod(method)) { continue; } MetadataRecord record = transform.HandleQualifiedMethod(typicalMethod); // As a twist, instantiated generic methods appear as if instantiated over their formals. if (typicalMethod.HasInstantiation) { var methodInst = new MethodInstantiation { Method = record, }; methodInst.GenericTypeArguments.Capacity = typicalMethod.Instantiation.Length; foreach (EcmaGenericParameter typeArgument in typicalMethod.Instantiation) { var genericParam = new TypeReference { TypeName = (ConstantStringValue)typeArgument.Name, }; methodInst.GenericTypeArguments.Add(genericParam); } record = methodInst; } stackTraceRecords.Add(new KeyValuePair <MethodDesc, MetadataRecord>( method, record)); writer.AdditionalRootRecords.Add(record); } var ms = new MemoryStream(); // .NET metadata is UTF-16 and UTF-16 contains code points that don't translate to UTF-8. var noThrowUtf8Encoding = new UTF8Encoding(false, false); using (var logWriter = _metadataLogFile != null ? new StreamWriter(File.Open(_metadataLogFile, FileMode.Create, FileAccess.Write, FileShare.Read), noThrowUtf8Encoding) : null) { writer.LogWriter = logWriter; writer.Write(ms); } metadataBlob = ms.ToArray(); typeMappings = new List <MetadataMapping <MetadataType> >(); methodMappings = new List <MetadataMapping <MethodDesc> >(); fieldMappings = new List <MetadataMapping <FieldDesc> >(); stackTraceMapping = new List <MetadataMapping <MethodDesc> >(); // Generate type definition mappings foreach (var type in factory.MetadataManager.GetTypesWithEETypes()) { MetadataType definition = type.IsTypeDefinition ? type as MetadataType : null; if (definition == null) { continue; } MetadataRecord record = transformed.GetTransformedTypeDefinition(definition); // Reflection requires that we maintain type identity. Even if we only generated a TypeReference record, // if there is an EEType for it, we also need a mapping table entry for it. if (record == null) { record = transformed.GetTransformedTypeReference(definition); } if (record != null) { typeMappings.Add(new MetadataMapping <MetadataType>(definition, writer.GetRecordHandle(record))); } } foreach (var method in GetCompiledMethods()) { if (method.IsCanonicalMethod(CanonicalFormKind.Specific)) { // Canonical methods are not interesting. continue; } if (IsReflectionBlocked(method.Instantiation) || IsReflectionBlocked(method.OwningType.Instantiation)) { continue; } if ((GetMetadataCategory(method) & MetadataCategory.RuntimeMapping) == 0) { continue; } MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition()); if (record != null) { methodMappings.Add(new MetadataMapping <MethodDesc>(method, writer.GetRecordHandle(record))); } } foreach (var eetypeGenerated in GetTypesWithEETypes()) { if (eetypeGenerated.IsGenericDefinition) { continue; } if (eetypeGenerated.HasInstantiation) { // Collapsing of field map entries based on canonicalization, to avoid redundant equivalent entries TypeDesc canonicalType = eetypeGenerated.ConvertToCanonForm(CanonicalFormKind.Specific); if (canonicalType != eetypeGenerated && TypeGeneratesEEType(canonicalType)) { continue; } } foreach (FieldDesc field in eetypeGenerated.GetFields()) { if (IsReflectionBlocked(field.OwningType.Instantiation)) { continue; } Field record = transformed.GetTransformedFieldDefinition(field.GetTypicalFieldDefinition()); if (record != null) { fieldMappings.Add(new MetadataMapping <FieldDesc>(field, writer.GetRecordHandle(record))); } } } // Generate stack trace metadata mapping foreach (var stackTraceRecord in stackTraceRecords) { stackTraceMapping.Add(new MetadataMapping <MethodDesc>(stackTraceRecord.Key, writer.GetRecordHandle(stackTraceRecord.Value))); } }
private List <MetadataMapping <MethodDesc> > GenerateStackTraceMetadata(NodeFactory factory) { var transformed = MetadataTransform.Run(new NoDefinitionMetadataPolicy(), Array.Empty <ModuleDesc>()); MetadataTransform transform = transformed.Transform; // Generate metadata blob var writer = new MetadataWriter(); // Only emit stack trace metadata for those methods which don't have reflection metadata HashSet <MethodDesc> methodInvokeMap = new HashSet <MethodDesc>(); foreach (var mappingEntry in GetMethodMapping(factory)) { var method = mappingEntry.Entity; if (ShouldMethodBeInInvokeMap(method)) { methodInvokeMap.Add(method); } } // Generate entries in the blob for methods that will be necessary for stack trace purposes. var stackTraceRecords = new List <KeyValuePair <MethodDesc, MetadataRecord> >(); foreach (var methodBody in GetCompiledMethodBodies()) { NonExternMethodSymbolNode methodNode = methodBody as NonExternMethodSymbolNode; if (methodNode != null && !methodNode.HasCompiledBody) { continue; } MethodDesc method = methodBody.Method; if (methodInvokeMap.Contains(method)) { continue; } if (!_stackTraceEmissionPolicy.ShouldIncludeMethod(method)) { continue; } // In the metadata, we only represent the generic definition MethodDesc methodToGenerateMetadataFor = method.GetTypicalMethodDefinition(); MetadataRecord record = transform.HandleQualifiedMethod(methodToGenerateMetadataFor); // As a twist, instantiated generic methods appear as if instantiated over their formals. if (methodToGenerateMetadataFor.HasInstantiation) { var methodInst = new MethodInstantiation { Method = record, }; methodInst.GenericTypeArguments.Capacity = methodToGenerateMetadataFor.Instantiation.Length; foreach (EcmaGenericParameter typeArgument in methodToGenerateMetadataFor.Instantiation) { var genericParam = new TypeReference { TypeName = (ConstantStringValue)typeArgument.Name, }; methodInst.GenericTypeArguments.Add(genericParam); } record = methodInst; } stackTraceRecords.Add(new KeyValuePair <MethodDesc, MetadataRecord>( method, record)); writer.AdditionalRootRecords.Add(record); } var ms = new MemoryStream(); writer.Write(ms); _stackTraceBlob = ms.ToArray(); var result = new List <MetadataMapping <MethodDesc> >(); // Generate stack trace metadata mapping foreach (var stackTraceRecord in stackTraceRecords) { result.Add(new MetadataMapping <MethodDesc>(stackTraceRecord.Key, writer.GetRecordHandle(stackTraceRecord.Value))); } return(result); }
protected void ComputeMetadata <TPolicy>( TPolicy policy, NodeFactory factory, out byte[] metadataBlob, out List <MetadataMapping <MetadataType> > typeMappings, out List <MetadataMapping <MethodDesc> > methodMappings, out List <MetadataMapping <FieldDesc> > fieldMappings, out List <MetadataMapping <MethodDesc> > stackTraceMapping) where TPolicy : struct, IMetadataPolicy { var transformed = MetadataTransform.Run(policy, GetCompilationModulesWithMetadata()); MetadataTransform transform = transformed.Transform; // TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate // TypeReference records for _typeDefinitionsGenerated that don't have metadata. // (To be used in MissingMetadataException messages) // Generate metadata blob var writer = new MetadataWriter(); writer.ScopeDefinitions.AddRange(transformed.Scopes); // Generate entries in the blob for methods that will be necessary for stack trace purposes. var stackTraceRecords = new List <KeyValuePair <MethodDesc, MetadataRecord> >(); foreach (var methodBody in GetCompiledMethodBodies()) { MethodDesc method = methodBody.Method; MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); // Methods that will end up in the reflection invoke table should not have an entry in stack trace table // We'll try looking them up in reflection data at runtime. if (transformed.GetTransformedMethodDefinition(typicalMethod) != null && ShouldMethodBeInInvokeMap(method) && (GetMetadataCategory(method) & MetadataCategory.RuntimeMapping) != 0) { continue; } if (!_stackTraceEmissionPolicy.ShouldIncludeMethod(method)) { continue; } MetadataRecord record = CreateStackTraceRecord(transform, method); stackTraceRecords.Add(new KeyValuePair <MethodDesc, MetadataRecord>( method, record)); writer.AdditionalRootRecords.Add(record); } var ms = new MemoryStream(); // .NET metadata is UTF-16 and UTF-16 contains code points that don't translate to UTF-8. var noThrowUtf8Encoding = new UTF8Encoding(false, false); using (var logWriter = _metadataLogFile != null ? new StreamWriter(File.Open(_metadataLogFile, FileMode.Create, FileAccess.Write, FileShare.Read), noThrowUtf8Encoding) : null) { writer.LogWriter = logWriter; writer.Write(ms); } metadataBlob = ms.ToArray(); typeMappings = new List <MetadataMapping <MetadataType> >(); methodMappings = new List <MetadataMapping <MethodDesc> >(); fieldMappings = new List <MetadataMapping <FieldDesc> >(); stackTraceMapping = new List <MetadataMapping <MethodDesc> >(); // Generate type definition mappings foreach (var type in factory.MetadataManager.GetTypesWithEETypes()) { MetadataType definition = type.IsTypeDefinition ? type as MetadataType : null; if (definition == null) { continue; } MetadataRecord record = transformed.GetTransformedTypeDefinition(definition); // Reflection requires that we maintain type identity. Even if we only generated a TypeReference record, // if there is an EEType for it, we also need a mapping table entry for it. if (record == null) { record = transformed.GetTransformedTypeReference(definition); } if (record != null) { typeMappings.Add(new MetadataMapping <MetadataType>(definition, writer.GetRecordHandle(record))); } } HashSet <MethodDesc> canonicalGenericMethods = new HashSet <MethodDesc>(); foreach (var method in GetCompiledMethods()) { if ((method.HasInstantiation && method.IsCanonicalMethod(CanonicalFormKind.Specific)) || (!method.HasInstantiation && method.GetCanonMethodTarget(CanonicalFormKind.Specific) != method)) { // Methods that are not in their canonical form are not interesting with the exception // of generic methods: their dictionaries convey their identity. continue; } if (IsReflectionBlocked(method.Instantiation) || IsReflectionBlocked(method.OwningType.Instantiation)) { continue; } if ((GetMetadataCategory(method) & MetadataCategory.RuntimeMapping) == 0) { continue; } // If we already added a canonically equivalent generic method, skip this one. if (method.HasInstantiation && !canonicalGenericMethods.Add(method.GetCanonMethodTarget(CanonicalFormKind.Specific))) { continue; } MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition()); if (record != null) { methodMappings.Add(new MetadataMapping <MethodDesc>(method, writer.GetRecordHandle(record))); } } HashSet <FieldDesc> canonicalFields = new HashSet <FieldDesc>(); foreach (var field in GetFieldsWithRuntimeMapping()) { FieldDesc fieldToAdd = field; if (!field.IsStatic) { TypeDesc canonOwningType = field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific); if (canonOwningType != field.OwningType) { FieldDesc canonField = _typeSystemContext.GetFieldForInstantiatedType(field.GetTypicalFieldDefinition(), (InstantiatedType)canonOwningType); // If we already added a canonically equivalent field, skip this one. if (!canonicalFields.Add(canonField)) { continue; } fieldToAdd = canonField; } } Field record = transformed.GetTransformedFieldDefinition(fieldToAdd.GetTypicalFieldDefinition()); if (record != null) { fieldMappings.Add(new MetadataMapping <FieldDesc>(fieldToAdd, writer.GetRecordHandle(record))); } } // Generate stack trace metadata mapping foreach (var stackTraceRecord in stackTraceRecords) { stackTraceMapping.Add(new MetadataMapping <MethodDesc>(stackTraceRecord.Key, writer.GetRecordHandle(stackTraceRecord.Value))); } }