IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
StaticCompiler.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2014 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24
25using System;
26using System.Collections.Concurrent;
27using System.Collections.Generic;
28using System.IO;
29using System.Reflection.Metadata;
30using System.Reflection.PortableExecutable;
31
33using IKVM.Reflection;
35using IKVM.Runtime;
36
37using Type = IKVM.Reflection.Type;
38
39namespace IKVM.Tools.Importer
40{
41
43 {
44
45 readonly ConcurrentDictionary<string, Type> runtimeTypeCache = new();
46
47 readonly IDiagnosticHandler diagnostics;
48 internal Universe universe;
49 internal Assembly runtimeAssembly;
50 internal Assembly baseAssembly;
51 internal ImportState rootTarget;
52 internal int errorCount;
53
54 internal Universe Universe => universe;
55
61 {
62 this.diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics));
63 }
64
72 internal void Init(bool nonDeterministicOutput, DebugMode debug, IList<string> libpaths)
73 {
74 var options = UniverseOptions.ResolveMissingMembers | UniverseOptions.EnableFunctionPointers;
75 if (nonDeterministicOutput == false)
76 options |= UniverseOptions.DeterministicOutput;
77
78 // discover the core lib from the references
79 var coreLibName = FindCoreLibName(rootTarget.unresolvedReferences, libpaths);
80 if (coreLibName == null)
81 {
82 diagnostics.CoreClassesMissing();
83 throw new Exception();
84 }
85
86 universe = new Universe(options, coreLibName);
87 universe.ResolvedMissingMember += ResolvedMissingMember;
88
89 // enable embedded symbol writer
90 if (debug == DebugMode.Portable)
91 universe.SetSymbolWriterFactory(module => new PortablePdbSymbolWriter(module));
92 }
93
100 static string FindCoreLibName(IList<string> references, IList<string> libpaths)
101 {
102 if (references != null)
103 foreach (var reference in references)
104 if (GetAssemblyNameIfCoreLib(reference) is string coreLibName)
105 return coreLibName;
106
107 if (libpaths != null)
108 foreach (var libpath in libpaths)
109 foreach (var dll in Directory.GetFiles(libpath, "*.dll"))
110 if (GetAssemblyNameIfCoreLib(dll) is string coreLibName)
111 return coreLibName;
112
113 return null;
114 }
115
121 static string GetAssemblyNameIfCoreLib(string path)
122 {
123 if (File.Exists(path) == false)
124 return null;
125
126 try
127 {
128 using var st = File.OpenRead(path);
129 using var pe = new PEReader(st);
130 var mr = pe.GetMetadataReader();
131
132 foreach (var handle in mr.TypeDefinitions)
133 if (IsSystemObject(mr, handle))
134 return mr.GetString(mr.GetAssemblyDefinition().Name);
135
136 return null;
137 }
138 catch (System.BadImageFormatException)
139 {
140 return null;
141 }
142 catch (InvalidOperationException)
143 {
144 return null;
145 }
146 catch (IOException)
147 {
148 return null;
149 }
150 }
151
158 static bool IsSystemObject(MetadataReader reader, TypeDefinitionHandle th)
159 {
160 var td = reader.GetTypeDefinition(th);
161 var ns = reader.GetString(td.Namespace);
162 var nm = reader.GetString(td.Name);
163
164 return ns == "System" && nm == "Object";
165 }
166
167 void ResolvedMissingMember(Module requestingModule, MemberInfo member)
168 {
169 if (requestingModule != null && member is Type)
170 {
171 diagnostics.UnableToResolveType(requestingModule.Name, ((Type)member).FullName, member.Module.FullyQualifiedName);
172 }
173 }
174
175 internal Assembly Load(string assemblyString)
176 {
177 var asm = universe.Load(assemblyString);
178 if (asm.__IsMissing)
179 throw new FileNotFoundException(assemblyString);
180
181 return asm;
182 }
183
184 internal Assembly LoadFile(string path)
185 {
186 return universe.LoadFile(path);
187 }
188
189 internal Type GetRuntimeType(string name)
190 {
191 return runtimeTypeCache.GetOrAdd(name, runtimeAssembly.GetType);
192 }
193
194 internal Type GetTypeForMapXml(RuntimeClassLoader loader, string name)
195 {
196 return GetType(loader, name) ?? throw new FatalCompilerErrorException(DiagnosticEvent.MapFileTypeNotFound(name));
197 }
198
199 internal RuntimeJavaType GetClassForMapXml(RuntimeClassLoader loader, string name)
200 {
201 return loader.TryLoadClassByName(name) ?? throw new FatalCompilerErrorException(DiagnosticEvent.MapFileClassNotFound(name));
202 }
203
204 internal RuntimeJavaField GetFieldForMapXml(RuntimeClassLoader loader, string clazz, string name, string sig)
205 {
206 var fw = GetClassForMapXml(loader, clazz).GetFieldWrapper(name, sig);
207 if (fw == null)
208 throw new FatalCompilerErrorException(DiagnosticEvent.MapFileFieldNotFound(name, clazz));
209
210 fw.Link();
211 return fw;
212 }
213
214 internal Type GetType(RuntimeClassLoader loader, string name)
215 {
216 var ccl = (ImportClassLoader)loader;
217 return ccl.GetTypeFromReferencedAssembly(name);
218 }
219
220 internal static void LinkageError(string msg, RuntimeJavaType actualType, RuntimeJavaType expectedType, params object[] values)
221 {
222 object[] args = new object[values.Length + 2];
223 values.CopyTo(args, 2);
224 args[0] = AssemblyQualifiedName(actualType);
225 args[1] = AssemblyQualifiedName(expectedType);
226 string str = string.Format(msg, args);
227 if (actualType is RuntimeUnloadableJavaType && (expectedType is RuntimeManagedByteCodeJavaType || expectedType is RuntimeManagedJavaType))
228 {
229 str += string.Format("\n\t(Please add a reference to {0})", expectedType.TypeAsBaseType.Assembly.Location);
230 }
231
232 throw new FatalCompilerErrorException(DiagnosticEvent.LinkageError(str));
233 }
234
235 static string AssemblyQualifiedName(RuntimeJavaType javaType)
236 {
237 var loader = javaType.ClassLoader;
238 var acl = loader as RuntimeAssemblyClassLoader;
239 if (acl != null)
240 return javaType.Name + ", " + acl.GetAssembly(javaType).FullName;
241
242 var ccl = loader as ImportClassLoader;
243 if (ccl != null)
244 return javaType.Name + ", " + ccl.GetTypeWrapperFactory().ModuleBuilder.Assembly.FullName;
245
246 return javaType.Name + " (unknown assembly)";
247 }
248
249 internal void IssueMissingTypeMessage(Type type)
250 {
251 type = ReflectUtil.GetMissingType(type);
252 if (type.Assembly.__IsMissing)
253 diagnostics.MissingReference(type.FullName, type.Assembly.FullName);
254 else
255 diagnostics.MissingType(type.FullName, type.Assembly.FullName);
256 }
257
258 internal void SuppressWarning(ImportState options, Diagnostic diagnostic, string name)
259 {
260 options.suppressWarnings.Add($"{diagnostic.Id}:{name}");
261 }
262
263 }
264
265}
Runtime support for a class loader.
Represents a runtime Java type derived from a .NET assembly which was the result of the IKVM compiler...
Implements a RuntimeJavaType that exposes existing managed .NET types not the result of static compil...
Holds some state for an instance of ImportContext.
StaticCompiler(IDiagnosticHandler diagnostics)
Initializes a new instance.
Exposes methods to accept diagnostic invocations.
static DiagnosticEvent LinkageError(string arg0, Exception? exception=null, DiagnosticLocation location=default)
The 'LinkageError' diagnostic.
static DiagnosticEvent MapFileFieldNotFound(string arg0, string arg1, Exception? exception=null, DiagnosticLocation location=default)
The 'MapFileFieldNotFound' diagnostic.
static DiagnosticEvent MapFileTypeNotFound(string arg0, Exception? exception=null, DiagnosticLocation location=default)
The 'MapFileTypeNotFound' diagnostic.
static DiagnosticEvent MapFileClassNotFound(string arg0, Exception? exception=null, DiagnosticLocation location=default)
The 'MapFileClassNotFound' diagnostic.