Welcome to mirror list, hosted at ThFree Co, Russian Federation.

AddBypassNGenStep.cs « Linker.Steps « linker « src - github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: baf492fdd423c72c2c213d2a0300224e9d034c4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//
// AddBypassNGenStep.cs
//
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;

namespace Mono.Linker.Steps
{

	public class AddBypassNGenStep : BaseStep
	{

		AssemblyDefinition coreLibAssembly;
		CustomAttribute bypassNGenAttribute;

		protected override void ProcessAssembly (AssemblyDefinition assembly)
		{
			if (Annotations.GetAction (assembly) == AssemblyAction.AddBypassNGen) {
				coreLibAssembly = Context.Resolve (assembly.MainModule.TypeSystem.CoreLibrary);
				bypassNGenAttribute = null;
				if (assembly == coreLibAssembly) {
					EnsureBypassNGenAttribute (assembly.MainModule);
				}

				foreach (var type in assembly.MainModule.Types)
					ProcessType (type);
			}
		}

		void ProcessType (TypeDefinition type)
		{
			if (type.HasMethods)
				ProcessMethods (type.Methods, type.Module);

			if (type.HasNestedTypes)
				ProcessNestedTypes (type);
		}

		void ProcessMethods (Collection<MethodDefinition> methods, ModuleDefinition module)
		{
			foreach (var method in methods)
				if (!Annotations.IsMarked (method)) {
					EnsureBypassNGenAttribute (module);
					method.CustomAttributes.Add (bypassNGenAttribute);
				}
		}

		void ProcessNestedTypes (TypeDefinition type)
		{
			for (int i = 0; i < type.NestedTypes.Count; i++) {
				var nested = type.NestedTypes[i];
				ProcessType (nested);
			}
		}

		private void EnsureBypassNGenAttribute (ModuleDefinition targetModule)
		{
			if (bypassNGenAttribute != null) {
				return;
			}
			ModuleDefinition corelibMainModule = coreLibAssembly.MainModule;
			TypeReference bypassNGenAttributeRef = new TypeReference ("System.Runtime", "BypassNGenAttribute", corelibMainModule, targetModule.TypeSystem.CoreLibrary);
			TypeDefinition bypassNGenAttributeDef = corelibMainModule.MetadataResolver.Resolve (bypassNGenAttributeRef);
			MethodDefinition bypassNGenAttributeDefaultConstructor = null;

			if (bypassNGenAttributeDef == null) {
				// System.Runtime.BypassNGenAttribute is not found in corelib. Add it.
				TypeReference systemAttributeRef = new TypeReference ("System", "Attribute", corelibMainModule, targetModule.TypeSystem.CoreLibrary);
				TypeReference systemAttribute = corelibMainModule.MetadataResolver.Resolve (systemAttributeRef);
				systemAttribute = corelibMainModule.ImportReference (systemAttribute);

				if (systemAttribute == null)
					throw new System.ApplicationException ("System.Attribute is not found in " + targetModule.TypeSystem.CoreLibrary.Name);

				MethodReference systemAttributeDefaultConstructorRef = new MethodReference (".ctor", corelibMainModule.TypeSystem.Void, systemAttributeRef);
				MethodReference systemAttributeDefaultConstructor = corelibMainModule.MetadataResolver.Resolve (systemAttributeDefaultConstructorRef);
				systemAttributeDefaultConstructor = corelibMainModule.ImportReference (systemAttributeDefaultConstructor);

				if (systemAttributeDefaultConstructor == null)
					throw new System.ApplicationException ("System.Attribute has no default constructor");

				bypassNGenAttributeDef = new TypeDefinition ("System.Runtime", "BypassNGenAttribute", TypeAttributes.NotPublic | TypeAttributes.Sealed, systemAttribute);

				coreLibAssembly.MainModule.Types.Add (bypassNGenAttributeDef);

				if (Annotations.GetAction (coreLibAssembly) == AssemblyAction.Copy) {
					Annotations.SetAction (coreLibAssembly, AssemblyAction.Save);
				}

				const MethodAttributes ctorAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
				bypassNGenAttributeDefaultConstructor = new MethodDefinition (".ctor", ctorAttributes, coreLibAssembly.MainModule.TypeSystem.Void);
				var instructions = bypassNGenAttributeDefaultConstructor.Body.Instructions;
				instructions.Add (Instruction.Create (OpCodes.Ldarg_0));
				instructions.Add (Instruction.Create (OpCodes.Call, systemAttributeDefaultConstructor));
				instructions.Add (Instruction.Create (OpCodes.Ret));

				bypassNGenAttributeDef.Methods.Add (bypassNGenAttributeDefaultConstructor);
			} else {
				foreach (MethodDefinition method in bypassNGenAttributeDef.Methods) {
					if (method.IsConstructor && !method.IsStatic && !method.HasParameters) {
						bypassNGenAttributeDefaultConstructor = method;
						break;
					}
				}

				if (bypassNGenAttributeDefaultConstructor == null) {
					throw new System.ApplicationException ("System.Runtime.BypassNGenAttribute has no default constructor");
				}
			}

			MethodReference defaultConstructorReference = targetModule.ImportReference (bypassNGenAttributeDefaultConstructor);
			bypassNGenAttribute = new CustomAttribute (defaultConstructorReference);
		}
	}
}