2
Copyright (C) 2002-2012 Jeroen Frijters
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.
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:
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.
26
using IKVM.Reflection;
27
using IKVM.Reflection.Emit;
28
using Type = IKVM.Reflection.Type;
29
using System.Resources;
31
using System.Collections.Generic;
33
using System.Diagnostics;
34
using System.Text.RegularExpressions;
36
using System.Threading;
37
using IKVM.Attributes;
39
using System.Security.Permissions;
40
using System.Security;
41
using System.Runtime.CompilerServices;
43
namespace IKVM.Internal
45
sealed class CompilerClassLoader : ClassLoaderWrapper
47
private Dictionary<string, ClassItem> classes;
48
private Dictionary<string, RemapperTypeWrapper> remapped = new Dictionary<string, RemapperTypeWrapper>();
49
private string assemblyName;
50
private string assemblyFile;
51
private string assemblyDir;
52
private bool targetIsModule;
53
private AssemblyBuilder assemblyBuilder;
54
private IKVM.Internal.MapXml.Attribute[] assemblyAttributes;
55
private CompilerOptions options;
56
private AssemblyClassLoader[] referencedAssemblies;
57
private Dictionary<string, string> nameMappings = new Dictionary<string, string>();
58
private Dictionary<string, string> packages;
59
private Dictionary<string, List<TypeWrapper>> ghosts;
60
private TypeWrapper[] mappedExceptions;
61
private bool[] mappedExceptionsAllSubClasses;
62
private Dictionary<string, IKVM.Internal.MapXml.Class> mapxml_Classes;
63
private Dictionary<MethodKey, IKVM.Internal.MapXml.InstructionList> mapxml_MethodBodies;
64
private Dictionary<MethodKey, IKVM.Internal.MapXml.ReplaceMethodCall[]> mapxml_ReplacedMethods;
65
private Dictionary<MethodKey, IKVM.Internal.MapXml.InstructionList> mapxml_MethodPrologues;
66
private Dictionary<string, string> baseClasses;
67
private IKVM.Internal.MapXml.Root map;
68
private List<object> assemblyAnnotations;
69
private List<string> classesToCompile;
70
private List<CompilerClassLoader> peerReferences = new List<CompilerClassLoader>();
71
private Dictionary<string, string> peerLoading = new Dictionary<string, string>();
72
private Dictionary<string, TypeWrapper> importedStubTypes = new Dictionary<string, TypeWrapper>();
73
private List<ClassLoaderWrapper> internalsVisibleTo = new List<ClassLoaderWrapper>();
74
private List<TypeWrapper> dynamicallyImportedTypes = new List<TypeWrapper>();
75
private List<string> jarList = new List<string>();
76
private List<TypeWrapper> allwrappers;
78
internal CompilerClassLoader(AssemblyClassLoader[] referencedAssemblies, CompilerOptions options, string path, bool targetIsModule, string assemblyName, Dictionary<string, ClassItem> classes)
79
: base(options.codegenoptions, null)
81
this.referencedAssemblies = referencedAssemblies;
82
this.options = options;
83
this.classes = classes;
84
this.assemblyName = assemblyName;
85
FileInfo assemblyPath = new FileInfo(path);
86
this.assemblyFile = assemblyPath.Name;
87
this.assemblyDir = assemblyPath.DirectoryName;
88
this.targetIsModule = targetIsModule;
89
Tracer.Info(Tracer.Compiler, "Instantiate CompilerClassLoader for {0}", assemblyName);
92
internal bool ReserveName(string javaName)
94
return !classes.ContainsKey(javaName) && GetTypeWrapperFactory().ReserveName(javaName);
97
internal void AddNameMapping(string javaName, string typeName)
99
nameMappings.Add(javaName, typeName);
102
internal void AddReference(AssemblyClassLoader acl)
104
AssemblyClassLoader[] temp = new AssemblyClassLoader[referencedAssemblies.Length + 1];
105
Array.Copy(referencedAssemblies, 0, temp, 0, referencedAssemblies.Length);
106
temp[temp.Length - 1] = acl;
107
referencedAssemblies = temp;
110
internal void AddReference(CompilerClassLoader ccl)
112
peerReferences.Add(ccl);
115
internal AssemblyName GetAssemblyName()
117
return assemblyBuilder.GetName();
120
private static PermissionSet Combine(PermissionSet p1, PermissionSet p2)
133
internal ModuleBuilder CreateModuleBuilder()
135
AssemblyName name = new AssemblyName();
136
name.Name = assemblyName;
137
if (options.keyPair != null)
139
name.KeyPair = options.keyPair;
141
else if (options.publicKey != null)
143
name.SetPublicKey(options.publicKey);
145
name.Version = options.version;
147
StaticCompiler.Universe
148
.DefineDynamicAssembly(name, AssemblyBuilderAccess.ReflectionOnly, assemblyDir);
149
ModuleBuilder moduleBuilder;
150
moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName, assemblyFile, this.EmitDebugInfo);
151
if(this.EmitStackTraceInfo)
153
AttributeHelper.SetSourceFile(moduleBuilder, null);
155
if(this.EmitDebugInfo || this.EmitStackTraceInfo)
157
CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(JVM.Import(typeof(DebuggableAttribute)).GetConstructor(new Type[] { Types.Boolean, Types.Boolean }), new object[] { true, this.EmitDebugInfo });
158
assemblyBuilder.SetCustomAttribute(debugAttr);
160
AttributeHelper.SetRuntimeCompatibilityAttribute(assemblyBuilder);
161
if(options.baseAddress != 0)
163
moduleBuilder.__ImageBase = options.baseAddress;
165
if(options.fileAlignment != 0)
167
moduleBuilder.__FileAlignment = options.fileAlignment;
169
if(options.highentropyva)
171
moduleBuilder.__DllCharacteristics |= DllCharacteristics.HighEntropyVA;
173
return moduleBuilder;
176
public override string ToString()
178
return "CompilerClassLoader:" + options.assembly;
181
protected override TypeWrapper LoadClassImpl(string name, bool throwClassNotFoundException)
183
foreach(AssemblyClassLoader acl in referencedAssemblies)
185
TypeWrapper tw = acl.DoLoad(name);
191
if(!peerLoading.ContainsKey(name))
193
peerLoading.Add(name, null);
196
foreach(CompilerClassLoader ccl in peerReferences)
198
TypeWrapper tw = ccl.PeerLoad(name);
204
if(options.sharedclassloader != null && options.sharedclassloader[0] != this)
206
TypeWrapper tw = options.sharedclassloader[0].PeerLoad(name);
215
peerLoading.Remove(name);
218
TypeWrapper tw1 = GetTypeWrapperCompilerHook(name);
223
// HACK the peer loading mess above may have indirectly loaded the classes without returning it,
224
// so we try once more here
225
tw1 = GetLoadedClass(name);
230
return LoadGenericClass(name);
233
private TypeWrapper PeerLoad(string name)
235
// To keep the performance acceptable in cases where we're compiling many targets, we first check if the load can
236
// possibly succeed on this class loader, otherwise we'll end up doing a lot of futile recursive loading attempts.
237
if(classes.ContainsKey(name) || remapped.ContainsKey(name) || GetLoadedClass(name) != null)
239
TypeWrapper tw = LoadClassByDottedNameFast(name);
240
// HACK we don't want to load classes referenced by peers, hence the "== this" check
241
if(tw != null && tw.GetClassLoader() == this)
246
if(options.sharedclassloader != null && options.sharedclassloader[0] == this)
248
foreach(CompilerClassLoader ccl in options.sharedclassloader)
252
TypeWrapper tw = ccl.PeerLoad(name);
263
private TypeWrapper GetTypeWrapperCompilerHook(string name)
265
RemapperTypeWrapper rtw;
266
if(remapped.TryGetValue(name, out rtw))
273
if(classes.TryGetValue(name, out classdef))
275
classes.Remove(name);
279
ClassFileParseOptions cfp = ClassFileParseOptions.LocalVariableTable;
280
if(this.EmitStackTraceInfo)
282
cfp |= ClassFileParseOptions.LineNumberTable;
284
f = new ClassFile(classdef.data, 0, classdef.data.Length, name, cfp);
286
catch(ClassFormatError x)
288
StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, x.Message);
291
if(options.removeUnusedFields)
293
f.RemoveUnusedFields();
295
if(f.IsPublic && options.privatePackages != null)
297
foreach(string p in options.privatePackages)
299
if(f.Name.StartsWith(p))
306
if(f.IsPublic && options.publicPackages != null)
309
foreach(string package in options.publicPackages)
311
if(f.Name.StartsWith(package))
327
&& !baseClasses.ContainsKey(f.Name)
328
&& !options.targetIsModule
329
&& options.sharedclassloader == null)
331
f.SetEffectivelyFinal();
333
if(f.SourceFileAttribute != null)
335
if(classdef.path != null)
337
string sourceFile = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(classdef.path), f.SourceFileAttribute));
338
if(File.Exists(sourceFile))
340
f.SourcePath = sourceFile;
343
if(f.SourcePath == null)
345
if (options.sourcepath != null)
347
string package = f.Name;
348
int index = package.LastIndexOf('.');
349
package = index == -1 ? "" : package.Substring(0, index).Replace('.', '/');
350
f.SourcePath = Path.GetFullPath(Path.Combine(options.sourcepath + "/" + package, f.SourceFileAttribute));
354
f.SourcePath = f.SourceFileAttribute;
360
TypeWrapper type = DefineClass(f, null);
361
if(f.IKVMAssemblyAttribute != null)
363
importedStubTypes.Add(f.Name, type);
367
catch (ClassFormatError x)
369
StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, x.Message);
372
catch (IllegalAccessError x)
374
StaticCompiler.IssueMessage(options, Message.IllegalAccessError, name, x.Message);
377
catch (VerifyError x)
379
StaticCompiler.IssueMessage(options, Message.VerificationError, name, x.Message);
382
catch (NoClassDefFoundError x)
384
StaticCompiler.IssueMessage(options, Message.NoClassDefFoundError, name, x.Message);
387
catch (RetargetableJavaException x)
389
StaticCompiler.IssueMessage(options, Message.GenericUnableToCompileError, name, x.GetType().Name, x.Message);
400
internal override Type GetGenericTypeDefinition(string name)
402
foreach(AssemblyClassLoader loader in referencedAssemblies)
404
Type type = loader.GetGenericTypeDefinition(name);
413
// HACK when we're compiling multiple targets with -sharedclassloader, each target will have its own CompilerClassLoader,
414
// so we need to consider them equivalent (because they represent the same class loader).
415
internal bool IsEquivalentTo(ClassLoaderWrapper other)
421
CompilerClassLoader ccl = other as CompilerClassLoader;
422
if (ccl != null && options.sharedclassloader != null && options.sharedclassloader.Contains(ccl))
424
if (!internalsVisibleTo.Contains(ccl))
426
AddInternalsVisibleToAttribute(ccl);
433
internal override bool InternalsVisibleToImpl(TypeWrapper wrapper, TypeWrapper friend)
435
Debug.Assert(wrapper.GetClassLoader() == this);
436
ClassLoaderWrapper other = friend.GetClassLoader();
437
// TODO ideally we should also respect InternalsVisibleToAttribute.Annotation here
438
if (this == other || internalsVisibleTo.Contains(other))
442
CompilerClassLoader ccl = other as CompilerClassLoader;
445
AddInternalsVisibleToAttribute(ccl);
451
private void AddInternalsVisibleToAttribute(CompilerClassLoader ccl)
453
internalsVisibleTo.Add(ccl);
454
AssemblyBuilder asm = ccl.assemblyBuilder;
455
AssemblyName asmName = asm.GetName();
456
string name = asmName.Name;
457
byte[] pubkey = asmName.GetPublicKey();
458
if (pubkey == null && asmName.KeyPair != null)
460
pubkey = asmName.KeyPair.PublicKey;
462
if (pubkey != null && pubkey.Length != 0)
464
StringBuilder sb = new StringBuilder(name);
465
sb.Append(", PublicKey=");
466
foreach (byte b in pubkey)
468
sb.AppendFormat("{0:X2}", b);
470
name = sb.ToString();
472
CustomAttributeBuilder cab = new CustomAttributeBuilder(JVM.Import(typeof(InternalsVisibleToAttribute)).GetConstructor(new Type[] { Types.String }), new object[] { name });
473
this.assemblyBuilder.SetCustomAttribute(cab);
476
internal void SetMain(MethodInfo m, PEFileKinds target, Dictionary<string, string> props, bool noglobbing, Type apartmentAttributeType)
478
MethodBuilder mainStub = this.GetTypeWrapperFactory().ModuleBuilder.DefineGlobalMethod("main", MethodAttributes.Public | MethodAttributes.Static, Types.Int32, new Type[] { Types.String.MakeArrayType() });
479
if(apartmentAttributeType != null)
481
mainStub.SetCustomAttribute(new CustomAttributeBuilder(apartmentAttributeType.GetConstructor(Type.EmptyTypes), new object[0]));
483
CodeEmitter ilgen = CodeEmitter.Create(mainStub);
484
CodeEmitterLocal rc = ilgen.DeclareLocal(Types.Int32);
485
TypeWrapper startupType = LoadClassByDottedName("ikvm.runtime.Startup");
488
ilgen.Emit(OpCodes.Newobj, JVM.Import(typeof(System.Collections.Generic.Dictionary<string, string>)).GetConstructor(Type.EmptyTypes));
489
foreach(KeyValuePair<string, string> kv in props)
491
ilgen.Emit(OpCodes.Dup);
492
ilgen.Emit(OpCodes.Ldstr, kv.Key);
493
ilgen.Emit(OpCodes.Ldstr, kv.Value);
494
if(kv.Value.IndexOf('%') < kv.Value.LastIndexOf('%'))
496
ilgen.Emit(OpCodes.Call, JVM.Import(typeof(Environment)).GetMethod("ExpandEnvironmentVariables", new Type[] { Types.String }));
498
ilgen.Emit(OpCodes.Callvirt, JVM.Import(typeof(System.Collections.Generic.Dictionary<string, string>)).GetMethod("Add"));
500
startupType.GetMethodWrapper("setProperties", "(Lcli.System.Collections.IDictionary;)V", false).EmitCall(ilgen);
502
ilgen.BeginExceptionBlock();
503
startupType.GetMethodWrapper("enterMainThread", "()V", false).EmitCall(ilgen);
504
ilgen.Emit(OpCodes.Ldarg_0);
507
ilgen.Emit(OpCodes.Ldc_I4_0);
508
startupType.GetMethodWrapper("glob", "([Ljava.lang.String;I)[Ljava.lang.String;", false).EmitCall(ilgen);
510
ilgen.Emit(OpCodes.Call, m);
511
CodeEmitterLabel label = ilgen.DefineLabel();
512
ilgen.EmitLeave(label);
513
ilgen.BeginCatchBlock(Types.Exception);
514
LoadClassByDottedName("ikvm.runtime.Util").GetMethodWrapper("mapException", "(Ljava.lang.Throwable;)Ljava.lang.Throwable;", false).EmitCall(ilgen);
515
CodeEmitterLocal exceptionLocal = ilgen.DeclareLocal(Types.Exception);
516
ilgen.Emit(OpCodes.Stloc, exceptionLocal);
517
TypeWrapper threadTypeWrapper = ClassLoaderWrapper.LoadClassCritical("java.lang.Thread");
518
CodeEmitterLocal threadLocal = ilgen.DeclareLocal(threadTypeWrapper.TypeAsLocalOrStackType);
519
threadTypeWrapper.GetMethodWrapper("currentThread", "()Ljava.lang.Thread;", false).EmitCall(ilgen);
520
ilgen.Emit(OpCodes.Stloc, threadLocal);
521
ilgen.Emit(OpCodes.Ldloc, threadLocal);
522
threadTypeWrapper.GetMethodWrapper("getThreadGroup", "()Ljava.lang.ThreadGroup;", false).EmitCallvirt(ilgen);
523
ilgen.Emit(OpCodes.Ldloc, threadLocal);
524
ilgen.Emit(OpCodes.Ldloc, exceptionLocal);
525
ClassLoaderWrapper.LoadClassCritical("java.lang.ThreadGroup").GetMethodWrapper("uncaughtException", "(Ljava.lang.Thread;Ljava.lang.Throwable;)V", false).EmitCallvirt(ilgen);
526
ilgen.Emit(OpCodes.Ldc_I4_1);
527
ilgen.Emit(OpCodes.Stloc, rc);
528
ilgen.EmitLeave(label);
529
ilgen.BeginFinallyBlock();
530
startupType.GetMethodWrapper("exitMainThread", "()V", false).EmitCall(ilgen);
531
ilgen.Emit(OpCodes.Endfinally);
532
ilgen.EndExceptionBlock();
533
ilgen.MarkLabel(label);
534
ilgen.Emit(OpCodes.Ldloc, rc);
535
ilgen.Emit(OpCodes.Ret);
537
assemblyBuilder.SetEntryPoint(mainStub, target);
540
private void PrepareSave()
542
((DynamicClassLoader)this.GetTypeWrapperFactory()).FinishAll();
547
ModuleBuilder mb = GetTypeWrapperFactory().ModuleBuilder;
550
// HACK force all referenced assemblies to end up as references in the assembly
551
// (even if they are otherwise unused), to make sure that the assembly class loader
552
// delegates to them at runtime.
553
// NOTE now we only do this for modules, when we're an assembly we store the exported
554
// assemblies in the ikvm.exports resource.
555
for(int i = 0;i < referencedAssemblies.Length; i++)
557
Type[] types = referencedAssemblies[i].MainAssembly.GetExportedTypes();
560
mb.GetTypeToken(types[0]);
564
mb.CreateGlobalFunctions();
566
AddJavaModuleAttribute(mb);
568
// add a package list and export map
569
if(options.sharedclassloader == null || options.sharedclassloader[0] == this)
571
string[] list = new string[packages.Count];
572
packages.Keys.CopyTo(list, 0);
573
mb.SetCustomAttribute(new CustomAttributeBuilder(JVM.LoadType(typeof(PackageListAttribute)).GetConstructor(new Type[] { JVM.Import(typeof(string[])) }), new object[] { list }));
574
// We can't add the resource when we're a module, because a multi-module assembly has a single resource namespace
575
// and since you cannot combine -target:module with -sharedclassloader we don't need an export map
576
// (the wildcard exports have already been added above, by making sure that we statically reference the assemblies).
585
Tracer.Info(Tracer.Compiler, "CompilerClassLoader saving {0} in {1}", assemblyFile, assemblyDir);
588
GetTypeWrapperFactory().ModuleBuilder.__Save(options.pekind, options.imageFileMachine);
592
throw new FatalCompilerErrorException(Message.ErrorWritingFile, GetTypeWrapperFactory().ModuleBuilder.FullyQualifiedName, x.Message);
597
Tracer.Info(Tracer.Compiler, "CompilerClassLoader saving {0} in {1}", assemblyFile, assemblyDir);
600
assemblyBuilder.Save(assemblyFile, options.pekind, options.imageFileMachine);
604
throw new FatalCompilerErrorException(Message.ErrorWritingFile, Path.Combine(assemblyDir, assemblyFile), x.Message);
609
private void AddJavaModuleAttribute(ModuleBuilder mb)
611
Type typeofJavaModuleAttribute = JVM.LoadType(typeof(JavaModuleAttribute));
612
PropertyInfo[] propInfos = new PropertyInfo[] {
613
typeofJavaModuleAttribute.GetProperty("Jars")
615
object[] propValues = new object[] {
618
if (nameMappings.Count > 0)
620
string[] list = new string[nameMappings.Count * 2];
622
foreach (KeyValuePair<string, string> kv in nameMappings)
625
list[i++] = kv.Value;
627
CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofJavaModuleAttribute.GetConstructor(new Type[] { JVM.Import(typeof(string[])) }), new object[] { list }, propInfos, propValues);
628
mb.SetCustomAttribute(cab);
632
CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofJavaModuleAttribute.GetConstructor(Type.EmptyTypes), new object[0], propInfos, propValues);
633
mb.SetCustomAttribute(cab);
637
private static void AddExportMapEntry(Dictionary<string, List<string>> map, CompilerClassLoader ccl, string name)
639
string assemblyName = ccl.assemblyBuilder.FullName;
641
if (!map.TryGetValue(assemblyName, out list))
643
list = new List<string>();
644
map.Add(assemblyName, list);
646
if (list != null) // if list is null, we already have a wildcard export for this assembly
652
private void AddWildcardExports(Dictionary<string, List<string>> exportedNamesPerAssembly)
654
foreach (AssemblyClassLoader acl in referencedAssemblies)
656
exportedNamesPerAssembly[acl.MainAssembly.FullName] = null;
660
private void WriteExportMap()
662
Dictionary<string, List<string>> exportedNamesPerAssembly = new Dictionary<string, List<string>>();
663
AddWildcardExports(exportedNamesPerAssembly);
664
foreach (TypeWrapper tw in dynamicallyImportedTypes)
666
AddExportMapEntry(exportedNamesPerAssembly, (CompilerClassLoader)tw.GetClassLoader(), tw.Name);
668
if (options.sharedclassloader == null)
670
foreach (CompilerClassLoader ccl in peerReferences)
672
exportedNamesPerAssembly[ccl.assemblyBuilder.FullName] = null;
677
foreach (CompilerClassLoader ccl in options.sharedclassloader)
681
ccl.AddWildcardExports(exportedNamesPerAssembly);
682
if (ccl.options.resources != null)
684
foreach (string name in ccl.options.resources.Keys)
686
AddExportMapEntry(exportedNamesPerAssembly, ccl, name);
689
if (ccl.options.externalResources != null)
691
foreach (string name in ccl.options.externalResources.Keys)
693
AddExportMapEntry(exportedNamesPerAssembly, ccl, name);
699
MemoryStream ms = new MemoryStream();
700
BinaryWriter bw = new BinaryWriter(ms);
701
bw.Write(exportedNamesPerAssembly.Count);
702
foreach (KeyValuePair<string, List<string>> kv in exportedNamesPerAssembly)
705
if (kv.Value == null)
712
Debug.Assert(kv.Value.Count != 0);
713
bw.Write(kv.Value.Count);
714
foreach (string name in kv.Value)
716
bw.Write(JVM.PersistableHash(name));
721
this.GetTypeWrapperFactory().ModuleBuilder.DefineManifestResource("ikvm.exports", ms, ResourceAttributes.Public);
724
internal void AddResources(Dictionary<string, List<ResourceItem>> resources, bool compressedResources)
726
Tracer.Info(Tracer.Compiler, "CompilerClassLoader adding resources...");
728
// BUG we need to call GetTypeWrapperFactory() to make sure that the assemblyBuilder is created (when building an empty target)
729
ModuleBuilder moduleBuilder = this.GetTypeWrapperFactory().ModuleBuilder;
730
Dictionary<string, Dictionary<string, ResourceItem>> jars = new Dictionary<string, Dictionary<string, ResourceItem>>();
732
foreach (KeyValuePair<string, List<ResourceItem>> kv in resources)
734
foreach (ResourceItem item in kv.Value)
737
string jarName = item.jar;
739
Dictionary<string, ResourceItem> jar;
740
if (!jars.TryGetValue(jarName, out jar))
742
jar = new Dictionary<string, ResourceItem>();
743
jars.Add(jarName, jar);
745
if (jar.ContainsKey(kv.Key))
747
jarName = Path.GetFileNameWithoutExtension(item.jar) + "-" + (count++) + Path.GetExtension(item.jar);
750
jar.Add(kv.Key, item);
754
foreach (KeyValuePair<string, Dictionary<string, ResourceItem>> jar in jars)
756
MemoryStream mem = new MemoryStream();
757
using (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zip = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(mem))
759
foreach (KeyValuePair<string, ResourceItem> kv in jar.Value)
761
ICSharpCode.SharpZipLib.Zip.ZipEntry zipEntry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(kv.Key);
762
if (kv.Value.zipEntry == null)
764
zipEntry.CompressionMethod = ICSharpCode.SharpZipLib.Zip.CompressionMethod.Stored;
768
zipEntry.Comment = kv.Value.zipEntry.Comment;
769
zipEntry.CompressionMethod = kv.Value.zipEntry.CompressionMethod;
770
zipEntry.DosTime = kv.Value.zipEntry.DosTime;
771
zipEntry.ExternalFileAttributes = kv.Value.zipEntry.ExternalFileAttributes;
772
zipEntry.ExtraData = kv.Value.zipEntry.ExtraData;
773
zipEntry.Flags = kv.Value.zipEntry.Flags;
775
if (compressedResources || zipEntry.CompressionMethod != ICSharpCode.SharpZipLib.Zip.CompressionMethod.Stored)
778
zipEntry.CompressionMethod = ICSharpCode.SharpZipLib.Zip.CompressionMethod.Deflated;
780
zip.PutNextEntry(zipEntry);
781
if (kv.Value.data != null)
783
zip.Write(kv.Value.data, 0, kv.Value.data.Length);
788
mem = new MemoryStream(mem.ToArray());
789
string name = jar.Key;
790
if (options.targetIsModule)
792
name = Path.GetFileNameWithoutExtension(name) + "-" + moduleBuilder.ModuleVersionId.ToString("N") + Path.GetExtension(name);
795
moduleBuilder.DefineManifestResource(name, mem, ResourceAttributes.Public);
799
private static MethodAttributes MapMethodAccessModifiers(IKVM.Internal.MapXml.MapModifiers mod)
801
const IKVM.Internal.MapXml.MapModifiers access = IKVM.Internal.MapXml.MapModifiers.Public | IKVM.Internal.MapXml.MapModifiers.Protected | IKVM.Internal.MapXml.MapModifiers.Private;
804
case IKVM.Internal.MapXml.MapModifiers.Public:
805
return MethodAttributes.Public;
806
case IKVM.Internal.MapXml.MapModifiers.Protected:
807
return MethodAttributes.FamORAssem;
808
case IKVM.Internal.MapXml.MapModifiers.Private:
809
return MethodAttributes.Private;
811
return MethodAttributes.Assembly;
815
private static FieldAttributes MapFieldAccessModifiers(IKVM.Internal.MapXml.MapModifiers mod)
817
const IKVM.Internal.MapXml.MapModifiers access = IKVM.Internal.MapXml.MapModifiers.Public | IKVM.Internal.MapXml.MapModifiers.Protected | IKVM.Internal.MapXml.MapModifiers.Private;
820
case IKVM.Internal.MapXml.MapModifiers.Public:
821
return FieldAttributes.Public;
822
case IKVM.Internal.MapXml.MapModifiers.Protected:
823
return FieldAttributes.FamORAssem;
824
case IKVM.Internal.MapXml.MapModifiers.Private:
825
return FieldAttributes.Private;
827
return FieldAttributes.Assembly;
831
private sealed class RemapperTypeWrapper : TypeWrapper
833
private CompilerClassLoader classLoader;
834
private TypeBuilder typeBuilder;
835
private TypeBuilder helperTypeBuilder;
836
private Type shadowType;
837
private IKVM.Internal.MapXml.Class classDef;
838
private TypeWrapper baseTypeWrapper;
839
private TypeWrapper[] interfaceWrappers;
841
internal override ClassLoaderWrapper GetClassLoader()
846
internal override bool IsRemapped
854
private static TypeWrapper GetBaseWrapper(IKVM.Internal.MapXml.Class c)
856
if((c.Modifiers & IKVM.Internal.MapXml.MapModifiers.Interface) != 0)
860
if(c.Name == "java.lang.Object")
864
return CoreClasses.java.lang.Object.Wrapper;
867
internal RemapperTypeWrapper(CompilerClassLoader classLoader, IKVM.Internal.MapXml.Class c, IKVM.Internal.MapXml.Root map)
868
: base((Modifiers)c.Modifiers, c.Name)
870
this.classLoader = classLoader;
871
this.baseTypeWrapper = GetBaseWrapper(c);
873
bool baseIsSealed = false;
874
shadowType = StaticCompiler.Universe.GetType(c.Shadows, true);
875
classLoader.SetRemappedType(shadowType, this);
876
Type baseType = shadowType;
877
Type baseInterface = null;
878
if(baseType.IsInterface)
880
baseInterface = baseType;
882
TypeAttributes attrs = TypeAttributes.Public;
883
if((c.Modifiers & IKVM.Internal.MapXml.MapModifiers.Interface) == 0)
885
attrs |= TypeAttributes.Class;
886
if(baseType.IsSealed)
889
attrs |= TypeAttributes.Abstract | TypeAttributes.Sealed;
894
attrs |= TypeAttributes.Interface | TypeAttributes.Abstract;
897
if((c.Modifiers & IKVM.Internal.MapXml.MapModifiers.Abstract) != 0)
899
attrs |= TypeAttributes.Abstract;
901
string name = c.Name.Replace('/', '.');
902
typeBuilder = classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(name, attrs, baseIsSealed ? Types.Object : baseType);
903
if(c.Attributes != null)
905
foreach(IKVM.Internal.MapXml.Attribute custattr in c.Attributes)
907
AttributeHelper.SetCustomAttribute(classLoader, typeBuilder, custattr);
910
if(baseInterface != null)
912
typeBuilder.AddInterfaceImplementation(baseInterface);
914
if(classLoader.EmitStackTraceInfo)
916
AttributeHelper.SetSourceFile(typeBuilder, Path.GetFileName(classLoader.options.remapfile));
921
AttributeHelper.SetModifiers(typeBuilder, (Modifiers)c.Modifiers, false);
924
if(c.scope == IKVM.Internal.MapXml.Scope.Public)
926
// FXBUG we would like to emit an attribute with a Type argument here, but that doesn't work because
927
// of a bug in SetCustomAttribute that causes type arguments to be serialized incorrectly (if the type
928
// is in the same assembly). Normally we use AttributeHelper.FreezeDry to get around this, but that doesn't
929
// work in this case (no attribute is emitted at all). So we work around by emitting a string instead
930
AttributeHelper.SetRemappedClass(classLoader.assemblyBuilder, name, shadowType);
932
AttributeHelper.SetRemappedType(typeBuilder, shadowType);
935
List<MethodWrapper> methods = new List<MethodWrapper>();
937
if(c.Constructors != null)
939
foreach(IKVM.Internal.MapXml.Constructor m in c.Constructors)
941
methods.Add(new RemappedConstructorWrapper(this, m));
945
if(c.Methods != null)
947
foreach(IKVM.Internal.MapXml.Method m in c.Methods)
949
methods.Add(new RemappedMethodWrapper(this, m, map, false));
952
// add methods from our super classes (e.g. Throwable should have Object's methods)
953
if(!this.IsFinal && !this.IsInterface && this.BaseTypeWrapper != null)
955
foreach(MethodWrapper mw in BaseTypeWrapper.GetMethods())
957
RemappedMethodWrapper rmw = mw as RemappedMethodWrapper;
958
if(rmw != null && (rmw.IsPublic || rmw.IsProtected))
960
if(!FindMethod(methods, rmw.Name, rmw.Signature))
962
methods.Add(new RemappedMethodWrapper(this, rmw.XmlMethod, map, true));
968
SetMethods(methods.ToArray());
971
internal sealed override TypeWrapper BaseTypeWrapper
973
get { return baseTypeWrapper; }
976
internal void LoadInterfaces(IKVM.Internal.MapXml.Class c)
978
if (c.Interfaces != null)
980
interfaceWrappers = new TypeWrapper[c.Interfaces.Length];
981
for (int i = 0; i < c.Interfaces.Length; i++)
983
interfaceWrappers[i] = classLoader.LoadClassByDottedName(c.Interfaces[i].Name);
988
interfaceWrappers = TypeWrapper.EmptyArray;
992
private static bool FindMethod(List<MethodWrapper> methods, string name, string sig)
994
foreach(MethodWrapper mw in methods)
996
if(mw.Name == name && mw.Signature == sig)
1004
abstract class RemappedMethodBaseWrapper : MethodWrapper
1006
internal RemappedMethodBaseWrapper(RemapperTypeWrapper typeWrapper, string name, string sig, Modifiers modifiers)
1007
: base(typeWrapper, name, sig, null, null, null, modifiers, MemberFlags.None)
1011
internal abstract MethodBase DoLink();
1013
internal abstract void Finish();
1016
sealed class RemappedConstructorWrapper : RemappedMethodBaseWrapper
1018
private IKVM.Internal.MapXml.Constructor m;
1019
private MethodBuilder mbHelper;
1021
internal RemappedConstructorWrapper(RemapperTypeWrapper typeWrapper, IKVM.Internal.MapXml.Constructor m)
1022
: base(typeWrapper, "<init>", m.Sig, (Modifiers)m.Modifiers)
1027
internal override void EmitCall(CodeEmitter ilgen)
1029
ilgen.Emit(OpCodes.Call, GetMethod());
1032
internal override void EmitNewobj(CodeEmitter ilgen)
1034
if(mbHelper != null)
1036
ilgen.Emit(OpCodes.Call, mbHelper);
1040
ilgen.Emit(OpCodes.Newobj, GetMethod());
1044
internal override MethodBase DoLink()
1046
MethodAttributes attr = MapMethodAccessModifiers(m.Modifiers);
1047
RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)DeclaringType;
1048
Type[] paramTypes = typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig);
1050
MethodBuilder cbCore = null;
1052
if(typeWrapper.shadowType.IsSealed)
1054
mbHelper = typeWrapper.typeBuilder.DefineMethod("newhelper", attr | MethodAttributes.Static, CallingConventions.Standard, typeWrapper.shadowType, paramTypes);
1055
if(m.Attributes != null)
1057
foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
1059
AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mbHelper, custattr);
1062
SetParameters(DeclaringType.GetClassLoader(), mbHelper, m.Params);
1063
AttributeHelper.SetModifiers(mbHelper, (Modifiers)m.Modifiers, false);
1064
AttributeHelper.SetNameSig(mbHelper, "<init>", m.Sig);
1065
AddDeclaredExceptions(mbHelper, m.throws);
1069
cbCore = ReflectUtil.DefineConstructor(typeWrapper.typeBuilder, attr, paramTypes);
1070
if(m.Attributes != null)
1072
foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
1074
AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), cbCore, custattr);
1077
SetParameters(DeclaringType.GetClassLoader(), cbCore, m.Params);
1078
AddDeclaredExceptions(cbCore, m.throws);
1083
internal override void Finish()
1085
// TODO we should insert method tracing (if enabled)
1087
Type[] paramTypes = this.GetParametersForDefineMethod();
1089
MethodBuilder cbCore = GetMethod() as MethodBuilder;
1093
CodeEmitter ilgen = CodeEmitter.Create(cbCore);
1094
// TODO we need to support ghost (and other funky?) parameter types
1097
// TODO do we need return type conversion here?
1098
m.body.Emit(DeclaringType.GetClassLoader(), ilgen);
1102
ilgen.Emit(OpCodes.Ldarg_0);
1103
for(int i = 0; i < paramTypes.Length; i++)
1105
ilgen.EmitLdarg(i + 1);
1107
if(m.redirect != null)
1109
throw new NotImplementedException();
1113
ConstructorInfo baseCon = DeclaringType.TypeAsTBD.GetConstructor(paramTypes);
1116
// TODO better error handling
1117
throw new InvalidOperationException("base class constructor not found: " + DeclaringType.Name + ".<init>" + m.Sig);
1119
ilgen.Emit(OpCodes.Call, baseCon);
1121
ilgen.Emit(OpCodes.Ret);
1124
if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo)
1126
ilgen.EmitLineNumberTable(cbCore);
1130
if(mbHelper != null)
1132
CodeEmitter ilgen = CodeEmitter.Create(mbHelper);
1133
if(m.redirect != null)
1135
m.redirect.Emit(DeclaringType.GetClassLoader(), ilgen);
1137
else if(m.alternateBody != null)
1139
m.alternateBody.Emit(DeclaringType.GetClassLoader(), ilgen);
1141
else if(m.body != null)
1143
// <body> doesn't make sense for helper constructors (which are actually factory methods)
1144
throw new InvalidOperationException();
1148
ConstructorInfo baseCon = DeclaringType.TypeAsTBD.GetConstructor(paramTypes);
1151
// TODO better error handling
1152
throw new InvalidOperationException("constructor not found: " + DeclaringType.Name + ".<init>" + m.Sig);
1154
for(int i = 0; i < paramTypes.Length; i++)
1158
ilgen.Emit(OpCodes.Newobj, baseCon);
1159
ilgen.Emit(OpCodes.Ret);
1162
if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo)
1164
ilgen.EmitLineNumberTable(mbHelper);
1170
sealed class RemappedMethodWrapper : RemappedMethodBaseWrapper
1172
private IKVM.Internal.MapXml.Method m;
1173
private IKVM.Internal.MapXml.Root map;
1174
private MethodBuilder mbHelper;
1175
private List<RemapperTypeWrapper> overriders = new List<RemapperTypeWrapper>();
1176
private bool inherited;
1178
internal RemappedMethodWrapper(RemapperTypeWrapper typeWrapper, IKVM.Internal.MapXml.Method m, IKVM.Internal.MapXml.Root map, bool inherited)
1179
: base(typeWrapper, m.Name, m.Sig, (Modifiers)m.Modifiers)
1183
this.inherited = inherited;
1186
internal IKVM.Internal.MapXml.Method XmlMethod
1194
internal override void EmitCall(CodeEmitter ilgen)
1196
if(!IsStatic && IsFinal)
1198
// When calling a final instance method on a remapped type from a class derived from a .NET class (i.e. a cli.System.Object or cli.System.Exception derived base class)
1199
// then we can't call the java.lang.Object or java.lang.Throwable methods and we have to go through the instancehelper_ method. Note that since the method
1200
// is final, this won't affect the semantics.
1201
EmitCallvirt(ilgen);
1205
ilgen.Emit(OpCodes.Call, (MethodInfo)GetMethod());
1209
internal override void EmitCallvirt(CodeEmitter ilgen)
1211
EmitCallvirtImpl(ilgen, this.IsProtected && !mbHelper.IsPublic);
1214
private void EmitCallvirtImpl(CodeEmitter ilgen, bool cloneOrFinalizeHack)
1216
if(mbHelper != null && !cloneOrFinalizeHack)
1218
ilgen.Emit(OpCodes.Call, mbHelper);
1222
ilgen.Emit(OpCodes.Callvirt, (MethodInfo)GetMethod());
1226
internal override MethodBase DoLink()
1228
RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)DeclaringType;
1230
if(typeWrapper.IsInterface)
1232
if(m.@override == null)
1234
throw new InvalidOperationException(typeWrapper.Name + "." + m.Name + m.Sig);
1236
MethodInfo interfaceMethod = typeWrapper.shadowType.GetMethod(m.@override.Name, typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig));
1237
if(interfaceMethod == null)
1239
throw new InvalidOperationException(typeWrapper.Name + "." + m.Name + m.Sig);
1241
// if any of the remapped types has a body for this interface method, we need a helper method
1242
// to special invocation through this interface for that type
1243
List<IKVM.Internal.MapXml.Class> specialCases = null;
1244
foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
1246
if(c.Methods != null)
1248
foreach(IKVM.Internal.MapXml.Method mm in c.Methods)
1250
if(mm.Name == m.Name && mm.Sig == m.Sig && mm.body != null)
1252
if(specialCases == null)
1254
specialCases = new List<IKVM.Internal.MapXml.Class>();
1256
specialCases.Add(c);
1263
if (m.throws == null)
1265
throws = new string[0];
1269
throws = new string[m.throws.Length];
1270
for (int i = 0; i < throws.Length; i++)
1272
throws[i] = m.throws[i].Class;
1275
AttributeHelper.SetRemappedInterfaceMethod(typeWrapper.typeBuilder, m.Name, m.@override.Name, throws);
1276
MethodBuilder helper = null;
1277
if(specialCases != null)
1280
Type[] temp = typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig);
1281
Type[] argTypes = new Type[temp.Length + 1];
1282
temp.CopyTo(argTypes, 1);
1283
argTypes[0] = typeWrapper.shadowType;
1284
if(typeWrapper.helperTypeBuilder == null)
1286
typeWrapper.helperTypeBuilder = typeWrapper.typeBuilder.DefineNestedType("__Helper", TypeAttributes.NestedPublic | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Abstract);
1287
AttributeHelper.HideFromJava(typeWrapper.helperTypeBuilder);
1289
helper = typeWrapper.helperTypeBuilder.DefineMethod(m.Name, MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, typeWrapper.GetClassLoader().RetTypeWrapperFromSig(m.Sig).TypeAsSignatureType, argTypes);
1290
if(m.Attributes != null)
1292
foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
1294
AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), helper, custattr);
1297
SetParameters(DeclaringType.GetClassLoader(), helper, m.Params);
1298
ilgen = CodeEmitter.Create(helper);
1299
foreach(IKVM.Internal.MapXml.Class c in specialCases)
1301
TypeWrapper tw = typeWrapper.GetClassLoader().LoadClassByDottedName(c.Name);
1302
ilgen.Emit(OpCodes.Ldarg_0);
1303
ilgen.Emit(OpCodes.Isinst, tw.TypeAsTBD);
1304
ilgen.Emit(OpCodes.Dup);
1305
CodeEmitterLabel label = ilgen.DefineLabel();
1306
ilgen.EmitBrfalse(label);
1307
for(int i = 1; i < argTypes.Length; i++)
1311
MethodWrapper mw = tw.GetMethodWrapper(m.Name, m.Sig, false);
1313
mw.EmitCallvirt(ilgen);
1314
ilgen.Emit(OpCodes.Ret);
1315
ilgen.MarkLabel(label);
1316
ilgen.Emit(OpCodes.Pop);
1318
for(int i = 0; i < argTypes.Length; i++)
1322
ilgen.Emit(OpCodes.Callvirt, interfaceMethod);
1323
ilgen.Emit(OpCodes.Ret);
1327
return interfaceMethod;
1331
MethodBuilder mbCore = null;
1332
Type[] paramTypes = typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig);
1333
Type retType = typeWrapper.GetClassLoader().RetTypeWrapperFromSig(m.Sig).TypeAsSignatureType;
1335
if(typeWrapper.shadowType.IsSealed && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0)
1337
// skip instance methods in sealed types, but we do need to add them to the overriders
1338
if(typeWrapper.BaseTypeWrapper != null && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Private) == 0)
1340
RemappedMethodWrapper baseMethod = typeWrapper.BaseTypeWrapper.GetMethodWrapper(m.Name, m.Sig, true) as RemappedMethodWrapper;
1341
if(baseMethod != null &&
1342
!baseMethod.IsFinal &&
1343
!baseMethod.IsPrivate &&
1344
(baseMethod.m.@override != null ||
1345
baseMethod.m.redirect != null ||
1346
baseMethod.m.body != null ||
1347
baseMethod.m.alternateBody != null))
1349
baseMethod.overriders.Add(typeWrapper);
1355
MethodInfo overrideMethod = null;
1356
MethodAttributes attr = MapMethodAccessModifiers(m.Modifiers) | MethodAttributes.HideBySig;
1357
if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) != 0)
1359
attr |= MethodAttributes.Static;
1361
else if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Private) == 0 && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Final) == 0)
1363
attr |= MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride;
1364
if(!typeWrapper.shadowType.IsSealed)
1366
MethodInfo autoOverride = typeWrapper.shadowType.GetMethod(m.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, paramTypes, null);
1367
if(autoOverride != null && autoOverride.ReturnType == retType && !autoOverride.IsFinal)
1369
// the method we're processing is overriding a method in its shadowType (which is the actual base type)
1370
attr &= ~MethodAttributes.NewSlot;
1373
if(typeWrapper.BaseTypeWrapper != null)
1375
RemappedMethodWrapper baseMethod = typeWrapper.BaseTypeWrapper.GetMethodWrapper(m.Name, m.Sig, true) as RemappedMethodWrapper;
1376
if(baseMethod != null)
1378
baseMethod.overriders.Add(typeWrapper);
1379
if(baseMethod.m.@override != null)
1381
overrideMethod = typeWrapper.BaseTypeWrapper.TypeAsTBD.GetMethod(baseMethod.m.@override.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, paramTypes, null);
1382
if(overrideMethod == null)
1384
throw new InvalidOperationException();
1390
mbCore = typeWrapper.typeBuilder.DefineMethod(m.Name, attr, CallingConventions.Standard, retType, paramTypes);
1391
if(m.Attributes != null)
1393
foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
1395
AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mbCore, custattr);
1398
SetParameters(DeclaringType.GetClassLoader(), mbCore, m.Params);
1399
if(overrideMethod != null && !inherited)
1401
typeWrapper.typeBuilder.DefineMethodOverride(mbCore, overrideMethod);
1405
AttributeHelper.HideFromReflection(mbCore);
1407
AddDeclaredExceptions(mbCore, m.throws);
1410
if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0 && !IsHideFromJava(m))
1412
// instance methods must have an instancehelper method
1413
MethodAttributes attr = MapMethodAccessModifiers(m.Modifiers) | MethodAttributes.HideBySig | MethodAttributes.Static;
1414
// NOTE instancehelpers for protected methods are made internal
1415
// and special cased in DotNetTypeWrapper.LazyPublishMembers
1416
if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Protected) != 0)
1418
attr &= ~MethodAttributes.MemberAccessMask;
1419
attr |= MethodAttributes.Assembly;
1421
Type[] exParamTypes = new Type[paramTypes.Length + 1];
1422
Array.Copy(paramTypes, 0, exParamTypes, 1, paramTypes.Length);
1423
exParamTypes[0] = typeWrapper.shadowType;
1424
mbHelper = typeWrapper.typeBuilder.DefineMethod("instancehelper_" + m.Name, attr, CallingConventions.Standard, retType, exParamTypes);
1425
if(m.Attributes != null)
1427
foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
1429
AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mbHelper, custattr);
1432
IKVM.Internal.MapXml.Param[] parameters;
1433
if(m.Params == null)
1435
parameters = new IKVM.Internal.MapXml.Param[1];
1439
parameters = new IKVM.Internal.MapXml.Param[m.Params.Length + 1];
1440
m.Params.CopyTo(parameters, 1);
1442
parameters[0] = new IKVM.Internal.MapXml.Param();
1443
parameters[0].Name = "this";
1444
SetParameters(DeclaringType.GetClassLoader(), mbHelper, parameters);
1445
if(!typeWrapper.IsFinal)
1447
AttributeHelper.SetEditorBrowsableNever(mbHelper);
1449
AttributeHelper.SetModifiers(mbHelper, (Modifiers)m.Modifiers, false);
1450
AttributeHelper.SetNameSig(mbHelper, m.Name, m.Sig);
1451
AddDeclaredExceptions(mbHelper, m.throws);
1452
mbHelper.SetCustomAttribute(new CustomAttributeBuilder(JVM.Import(typeof(ObsoleteAttribute)).GetConstructor(new Type[] { Types.String }), new object[] { "This function will be removed from future versions. Please use extension methods from ikvm.extensions namespace instead." }));
1458
private static bool IsHideFromJava(IKVM.Internal.MapXml.Method m)
1460
if (m.Attributes != null)
1462
foreach (MapXml.Attribute attr in m.Attributes)
1464
if (attr.Type == "IKVM.Attributes.HideFromJavaAttribute")
1473
internal override void Finish()
1475
// TODO we should insert method tracing (if enabled)
1476
Type[] paramTypes = this.GetParametersForDefineMethod();
1478
MethodBuilder mbCore = GetMethod() as MethodBuilder;
1480
// NOTE sealed types don't have instance methods (only instancehelpers)
1483
CodeEmitter ilgen = CodeEmitter.Create(mbCore);
1484
MethodInfo baseMethod = null;
1485
if(m.@override != null)
1487
baseMethod = DeclaringType.TypeAsTBD.GetMethod(m.@override.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, paramTypes, null);
1488
if(baseMethod == null)
1490
throw new InvalidOperationException();
1492
((TypeBuilder)DeclaringType.TypeAsBaseType).DefineMethodOverride(mbCore, baseMethod);
1494
// TODO we need to support ghost (and other funky?) parameter types
1497
// we manually walk the instruction list, because we need to special case the ret instructions
1498
IKVM.Internal.MapXml.CodeGenContext context = new IKVM.Internal.MapXml.CodeGenContext(DeclaringType.GetClassLoader());
1499
foreach(IKVM.Internal.MapXml.Instruction instr in m.body.invoke)
1501
if(instr is IKVM.Internal.MapXml.Ret)
1503
this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
1505
instr.Generate(context, ilgen);
1510
if(m.redirect != null && m.redirect.LineNumber != -1)
1512
ilgen.SetLineNumber((ushort)m.redirect.LineNumber);
1515
if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0)
1518
ilgen.Emit(OpCodes.Ldarg_0);
1520
for(int i = 0; i < paramTypes.Length; i++)
1522
ilgen.EmitLdarg(i + thisOffset);
1524
if(m.redirect != null)
1526
EmitRedirect(DeclaringType.TypeAsTBD, ilgen);
1530
if(baseMethod == null)
1532
throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
1534
ilgen.Emit(OpCodes.Call, baseMethod);
1536
this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
1537
ilgen.Emit(OpCodes.Ret);
1540
if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo)
1542
ilgen.EmitLineNumberTable(mbCore);
1546
// NOTE static methods don't have helpers
1547
// NOTE for interface helpers we don't have to do anything,
1548
// because they've already been generated in DoLink
1549
// (currently this only applies to Comparable.compareTo).
1550
if(mbHelper != null && !this.DeclaringType.IsInterface)
1552
CodeEmitter ilgen = CodeEmitter.Create(mbHelper);
1553
// check "this" for null
1554
if(m.@override != null && m.redirect == null && m.body == null && m.alternateBody == null)
1556
// we're going to be calling the overridden version, so we don't need the null check
1558
else if(!m.NoNullCheck)
1560
ilgen.Emit(OpCodes.Ldarg_0);
1561
ilgen.EmitNullCheck();
1563
if(mbCore != null &&
1564
(m.@override == null || m.redirect != null) &&
1565
(m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Private) == 0 && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Final) == 0)
1567
// TODO we should have a way to supress this for overridden methods
1568
ilgen.Emit(OpCodes.Ldarg_0);
1569
ilgen.Emit(OpCodes.Isinst, DeclaringType.TypeAsBaseType);
1570
ilgen.Emit(OpCodes.Dup);
1571
CodeEmitterLabel skip = ilgen.DefineLabel();
1572
ilgen.EmitBrfalse(skip);
1573
for(int i = 0; i < paramTypes.Length; i++)
1575
ilgen.EmitLdarg(i + 1);
1577
ilgen.Emit(OpCodes.Callvirt, mbCore);
1578
this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
1579
ilgen.Emit(OpCodes.Ret);
1580
ilgen.MarkLabel(skip);
1581
ilgen.Emit(OpCodes.Pop);
1583
foreach(RemapperTypeWrapper overrider in overriders)
1585
RemappedMethodWrapper mw = (RemappedMethodWrapper)overrider.GetMethodWrapper(Name, Signature, false);
1586
if(mw.m.redirect == null && mw.m.body == null && mw.m.alternateBody == null)
1588
// the overridden method doesn't actually do anything special (that means it will end
1589
// up calling the .NET method it overrides), so we don't need to special case this
1593
ilgen.Emit(OpCodes.Ldarg_0);
1594
ilgen.Emit(OpCodes.Isinst, overrider.TypeAsTBD);
1595
ilgen.Emit(OpCodes.Dup);
1596
CodeEmitterLabel skip = ilgen.DefineLabel();
1597
ilgen.EmitBrfalse(skip);
1598
for(int i = 0; i < paramTypes.Length; i++)
1600
ilgen.EmitLdarg(i + 1);
1603
mw.EmitCallvirtImpl(ilgen, false);
1604
this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
1605
ilgen.Emit(OpCodes.Ret);
1606
ilgen.MarkLabel(skip);
1607
ilgen.Emit(OpCodes.Pop);
1610
if(m.body != null || m.alternateBody != null)
1612
IKVM.Internal.MapXml.InstructionList body = m.alternateBody == null ? m.body : m.alternateBody;
1613
// we manually walk the instruction list, because we need to special case the ret instructions
1614
IKVM.Internal.MapXml.CodeGenContext context = new IKVM.Internal.MapXml.CodeGenContext(DeclaringType.GetClassLoader());
1615
foreach(IKVM.Internal.MapXml.Instruction instr in body.invoke)
1617
if(instr is IKVM.Internal.MapXml.Ret)
1619
this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
1621
instr.Generate(context, ilgen);
1626
if(m.redirect != null && m.redirect.LineNumber != -1)
1628
ilgen.SetLineNumber((ushort)m.redirect.LineNumber);
1630
Type shadowType = ((RemapperTypeWrapper)DeclaringType).shadowType;
1631
for(int i = 0; i < paramTypes.Length + 1; i++)
1635
if(m.redirect != null)
1637
EmitRedirect(shadowType, ilgen);
1639
else if(m.@override != null)
1641
MethodInfo baseMethod = shadowType.GetMethod(m.@override.Name, BindingFlags.Instance | BindingFlags.Public, null, paramTypes, null);
1642
if(baseMethod == null)
1644
throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
1646
ilgen.Emit(OpCodes.Callvirt, baseMethod);
1650
RemappedMethodWrapper baseMethod = DeclaringType.BaseTypeWrapper.GetMethodWrapper(Name, Signature, true) as RemappedMethodWrapper;
1651
if(baseMethod == null || baseMethod.m.@override == null)
1653
throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
1655
MethodInfo overrideMethod = shadowType.GetMethod(baseMethod.m.@override.Name, BindingFlags.Instance | BindingFlags.Public, null, paramTypes, null);
1656
if(overrideMethod == null)
1658
throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
1660
ilgen.Emit(OpCodes.Callvirt, overrideMethod);
1662
this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
1663
ilgen.Emit(OpCodes.Ret);
1666
if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo)
1668
ilgen.EmitLineNumberTable(mbHelper);
1672
// do we need a helper for non-virtual reflection invocation?
1673
if(m.nonvirtualAlternateBody != null || (m.@override != null && overriders.Count > 0))
1675
RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)DeclaringType;
1676
Type[] argTypes = new Type[paramTypes.Length + 1];
1677
argTypes[0] = typeWrapper.TypeAsSignatureType;
1678
this.GetParametersForDefineMethod().CopyTo(argTypes, 1);
1679
MethodBuilder mb = typeWrapper.typeBuilder.DefineMethod("nonvirtualhelper/" + this.Name, MethodAttributes.Private | MethodAttributes.Static, this.ReturnTypeForDefineMethod, argTypes);
1680
if(m.Attributes != null)
1682
foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
1684
AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mb, custattr);
1687
SetParameters(DeclaringType.GetClassLoader(), mb, m.Params);
1688
AttributeHelper.HideFromJava(mb);
1689
CodeEmitter ilgen = CodeEmitter.Create(mb);
1690
if(m.nonvirtualAlternateBody != null)
1692
m.nonvirtualAlternateBody.Emit(DeclaringType.GetClassLoader(), ilgen);
1696
Type shadowType = ((RemapperTypeWrapper)DeclaringType).shadowType;
1697
MethodInfo baseMethod = shadowType.GetMethod(m.@override.Name, BindingFlags.Instance | BindingFlags.Public, null, paramTypes, null);
1698
if(baseMethod == null)
1700
throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
1702
ilgen.Emit(OpCodes.Ldarg_0);
1703
for(int i = 0; i < paramTypes.Length; i++)
1705
ilgen.EmitLdarg(i + 1);
1707
ilgen.Emit(OpCodes.Call, baseMethod);
1708
ilgen.Emit(OpCodes.Ret);
1714
private void EmitRedirect(Type baseType, CodeEmitter ilgen)
1716
string redirName = m.redirect.Name;
1717
string redirSig = m.redirect.Sig;
1718
if(redirName == null)
1722
if(redirSig == null)
1726
ClassLoaderWrapper classLoader = DeclaringType.GetClassLoader();
1727
// HACK if the class name contains a comma, we assume it is a .NET type
1728
if(m.redirect.Class == null || m.redirect.Class.IndexOf(',') >= 0)
1730
// TODO better error handling
1731
Type type = m.redirect.Class == null ? baseType : StaticCompiler.Universe.GetType(m.redirect.Class, true);
1732
Type[] redirParamTypes = classLoader.ArgTypeListFromSig(redirSig);
1733
MethodInfo mi = type.GetMethod(m.redirect.Name, redirParamTypes);
1736
throw new InvalidOperationException();
1738
ilgen.Emit(OpCodes.Call, mi);
1742
TypeWrapper tw = classLoader.LoadClassByDottedName(m.redirect.Class);
1743
MethodWrapper mw = tw.GetMethodWrapper(redirName, redirSig, false);
1746
throw new InvalidOperationException("Missing redirect method: " + tw.Name + "." + redirName + redirSig);
1754
private static void SetParameters(ClassLoaderWrapper loader, MethodBuilder mb, IKVM.Internal.MapXml.Param[] parameters)
1756
if(parameters != null)
1758
for(int i = 0; i < parameters.Length; i++)
1760
ParameterBuilder pb = mb.DefineParameter(i + 1, ParameterAttributes.None, parameters[i].Name);
1761
if(parameters[i].Attributes != null)
1763
for(int j = 0; j < parameters[i].Attributes.Length; j++)
1765
AttributeHelper.SetCustomAttribute(loader, pb, parameters[i].Attributes[j]);
1772
internal void Process2ndPassStep1()
1774
if (!shadowType.IsSealed)
1776
foreach (TypeWrapper ifaceTypeWrapper in interfaceWrappers)
1778
typeBuilder.AddInterfaceImplementation(ifaceTypeWrapper.TypeAsBaseType);
1781
AttributeHelper.SetImplementsAttribute(typeBuilder, interfaceWrappers);
1784
internal void Process2ndPassStep2(IKVM.Internal.MapXml.Root map)
1786
IKVM.Internal.MapXml.Class c = classDef;
1787
TypeBuilder tb = typeBuilder;
1789
List<FieldWrapper> fields = new List<FieldWrapper>();
1791
// TODO fields should be moved to the RemapperTypeWrapper constructor as well
1792
if(c.Fields != null)
1794
foreach(IKVM.Internal.MapXml.Field f in c.Fields)
1797
FieldAttributes attr = MapFieldAccessModifiers(f.Modifiers);
1798
if(f.Constant != null)
1800
attr |= FieldAttributes.Literal;
1802
else if((f.Modifiers & IKVM.Internal.MapXml.MapModifiers.Final) != 0)
1804
attr |= FieldAttributes.InitOnly;
1806
if((f.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) != 0)
1808
attr |= FieldAttributes.Static;
1810
FieldBuilder fb = tb.DefineField(f.Name, GetClassLoader().FieldTypeWrapperFromSig(f.Sig).TypeAsSignatureType, attr);
1811
if(f.Attributes != null)
1813
foreach(IKVM.Internal.MapXml.Attribute custattr in f.Attributes)
1815
AttributeHelper.SetCustomAttribute(classLoader, fb, custattr);
1819
if(f.Constant != null)
1824
constant = long.Parse(f.Constant);
1827
// TODO support other types
1828
throw new NotImplementedException("remapped constant field of type: " + f.Sig);
1830
fb.SetConstant(constant);
1831
fields.Add(new ConstantFieldWrapper(this, GetClassLoader().FieldTypeWrapperFromSig(f.Sig), f.Name, f.Sig, (Modifiers)f.Modifiers, fb, constant, MemberFlags.None));
1835
fields.Add(FieldWrapper.Create(this, GetClassLoader().FieldTypeWrapperFromSig(f.Sig), fb, f.Name, f.Sig, new ExModifiers((Modifiers)f.Modifiers, false)));
1840
SetFields(fields.ToArray());
1843
internal void Process3rdPass()
1845
foreach(RemappedMethodBaseWrapper m in GetMethods())
1851
internal void Process4thPass(ICollection<RemapperTypeWrapper> remappedTypes)
1853
foreach(RemappedMethodBaseWrapper m in GetMethods())
1858
if(classDef.Clinit != null)
1860
MethodBuilder cb = ReflectUtil.DefineTypeInitializer(typeBuilder);
1861
CodeEmitter ilgen = CodeEmitter.Create(cb);
1862
// TODO emit code to make sure super class is initialized
1863
classDef.Clinit.body.Emit(classLoader, ilgen);
1867
// FXBUG because the AppDomain.TypeResolve event doesn't work correctly for inner classes,
1868
// we need to explicitly finish the interface we implement (if they are ghosts, we need the nested __Interface type)
1869
if(classDef.Interfaces != null)
1871
foreach(IKVM.Internal.MapXml.Interface iface in classDef.Interfaces)
1873
GetClassLoader().LoadClassByDottedName(iface.Name).Finish();
1877
CreateShadowInstanceOf(remappedTypes);
1878
CreateShadowCheckCast(remappedTypes);
1880
if(!shadowType.IsInterface)
1882
// For all inherited methods, we emit a method that hides the inherited method and
1883
// annotate it with EditorBrowsableAttribute(EditorBrowsableState.Never) to make
1884
// sure the inherited methods don't show up in Intellisense.
1885
Dictionary<string, MethodBuilder> methods = new Dictionary<string, MethodBuilder>();
1886
foreach(MethodWrapper mw in GetMethods())
1888
MethodBuilder mb = mw.GetMethod() as MethodBuilder;
1891
methods.Add(MakeMethodKey(mb), mb);
1894
foreach(MethodInfo mi in typeBuilder.BaseType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy))
1896
string key = MakeMethodKey(mi);
1897
if(!methods.ContainsKey(key))
1899
ParameterInfo[] paramInfo = mi.GetParameters();
1900
Type[] paramTypes = new Type[paramInfo.Length];
1901
for(int i = 0; i < paramInfo.Length; i++)
1903
paramTypes[i] = paramInfo[i].ParameterType;
1905
MethodBuilder mb = typeBuilder.DefineMethod(mi.Name, mi.Attributes & (MethodAttributes.MemberAccessMask | MethodAttributes.SpecialName | MethodAttributes.Static), mi.ReturnType, paramTypes);
1906
AttributeHelper.HideFromJava(mb);
1907
AttributeHelper.SetEditorBrowsableNever(mb);
1908
CopyLinkDemands(mb, mi);
1909
CodeEmitter ilgen = CodeEmitter.Create(mb);
1910
for(int i = 0; i < paramTypes.Length; i++)
1916
ilgen.EmitLdarg(paramTypes.Length);
1917
ilgen.Emit(OpCodes.Callvirt, mi);
1921
ilgen.Emit(OpCodes.Call, mi);
1923
ilgen.Emit(OpCodes.Ret);
1928
foreach(PropertyInfo pi in typeBuilder.BaseType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
1930
ParameterInfo[] paramInfo = pi.GetIndexParameters();
1931
Type[] paramTypes = new Type[paramInfo.Length];
1932
for(int i = 0; i < paramInfo.Length; i++)
1934
paramTypes[i] = paramInfo[i].ParameterType;
1936
PropertyBuilder pb = typeBuilder.DefineProperty(pi.Name, PropertyAttributes.None, pi.PropertyType, paramTypes);
1937
if(pi.GetGetMethod() != null)
1939
pb.SetGetMethod(methods[MakeMethodKey(pi.GetGetMethod())]);
1941
if(pi.GetSetMethod() != null)
1943
pb.SetSetMethod(methods[MakeMethodKey(pi.GetSetMethod())]);
1945
AttributeHelper.SetEditorBrowsableNever(pb);
1949
typeBuilder.CreateType();
1950
if(helperTypeBuilder != null)
1952
helperTypeBuilder.CreateType();
1956
private static void CopyLinkDemands(MethodBuilder mb, MethodInfo mi)
1958
foreach (CustomAttributeData cad in CustomAttributeData.__GetDeclarativeSecurity(mi))
1960
if (cad.ConstructorArguments.Count == 0 || (int)cad.ConstructorArguments[0].Value == (int)SecurityAction.LinkDemand)
1962
mb.__AddDeclarativeSecurity(cad.__ToBuilder());
1967
private static string MakeMethodKey(MethodInfo method)
1969
StringBuilder sb = new StringBuilder();
1970
sb.Append(method.ReturnType.AssemblyQualifiedName).Append(":").Append(method.Name);
1971
ParameterInfo[] paramInfo = method.GetParameters();
1972
Type[] paramTypes = new Type[paramInfo.Length];
1973
for(int i = 0; i < paramInfo.Length; i++)
1975
paramTypes[i] = paramInfo[i].ParameterType;
1976
sb.Append(":").Append(paramInfo[i].ParameterType.AssemblyQualifiedName);
1978
return sb.ToString();
1981
private void CreateShadowInstanceOf(ICollection<RemapperTypeWrapper> remappedTypes)
1983
// FXBUG .NET 1.1 doesn't allow static methods on interfaces
1984
if(typeBuilder.IsInterface)
1988
MethodAttributes attr = MethodAttributes.SpecialName | MethodAttributes.Public | MethodAttributes.Static;
1989
MethodBuilder mb = typeBuilder.DefineMethod("__<instanceof>", attr, Types.Boolean, new Type[] { Types.Object });
1990
AttributeHelper.HideFromJava(mb);
1991
AttributeHelper.SetEditorBrowsableNever(mb);
1992
CodeEmitter ilgen = CodeEmitter.Create(mb);
1994
ilgen.Emit(OpCodes.Ldarg_0);
1995
ilgen.Emit(OpCodes.Isinst, shadowType);
1996
CodeEmitterLabel retFalse = ilgen.DefineLabel();
1997
ilgen.EmitBrfalse(retFalse);
1999
if(!shadowType.IsSealed)
2001
ilgen.Emit(OpCodes.Ldarg_0);
2002
ilgen.Emit(OpCodes.Isinst, typeBuilder);
2003
ilgen.EmitBrtrue(retFalse);
2006
if(shadowType == Types.Object)
2008
ilgen.Emit(OpCodes.Ldarg_0);
2009
ilgen.Emit(OpCodes.Isinst, Types.Array);
2010
ilgen.EmitBrtrue(retFalse);
2013
foreach(RemapperTypeWrapper r in remappedTypes)
2015
if(!r.shadowType.IsInterface && r.shadowType.IsSubclassOf(shadowType))
2017
ilgen.Emit(OpCodes.Ldarg_0);
2018
ilgen.Emit(OpCodes.Isinst, r.shadowType);
2019
ilgen.EmitBrtrue(retFalse);
2022
ilgen.Emit(OpCodes.Ldc_I4_1);
2023
ilgen.Emit(OpCodes.Ret);
2025
ilgen.MarkLabel(retFalse);
2026
ilgen.Emit(OpCodes.Ldc_I4_0);
2027
ilgen.Emit(OpCodes.Ret);
2032
private void CreateShadowCheckCast(ICollection<RemapperTypeWrapper> remappedTypes)
2034
// FXBUG .NET 1.1 doesn't allow static methods on interfaces
2035
if(typeBuilder.IsInterface)
2039
MethodAttributes attr = MethodAttributes.SpecialName | MethodAttributes.Public | MethodAttributes.Static;
2040
MethodBuilder mb = typeBuilder.DefineMethod("__<checkcast>", attr, shadowType, new Type[] { Types.Object });
2041
AttributeHelper.HideFromJava(mb);
2042
AttributeHelper.SetEditorBrowsableNever(mb);
2043
CodeEmitter ilgen = CodeEmitter.Create(mb);
2045
CodeEmitterLabel fail = ilgen.DefineLabel();
2046
bool hasfail = false;
2048
if(!shadowType.IsSealed)
2050
ilgen.Emit(OpCodes.Ldarg_0);
2051
ilgen.Emit(OpCodes.Isinst, typeBuilder);
2052
ilgen.EmitBrtrue(fail);
2056
if(shadowType == Types.Object)
2058
ilgen.Emit(OpCodes.Ldarg_0);
2059
ilgen.Emit(OpCodes.Isinst, Types.Array);
2060
ilgen.EmitBrtrue(fail);
2064
foreach(RemapperTypeWrapper r in remappedTypes)
2066
if(!r.shadowType.IsInterface && r.shadowType.IsSubclassOf(shadowType))
2068
ilgen.Emit(OpCodes.Ldarg_0);
2069
ilgen.Emit(OpCodes.Isinst, r.shadowType);
2070
ilgen.EmitBrtrue(fail);
2074
ilgen.Emit(OpCodes.Ldarg_0);
2075
ilgen.EmitCastclass(shadowType);
2076
ilgen.Emit(OpCodes.Ret);
2080
ilgen.MarkLabel(fail);
2081
ilgen.ThrowException(JVM.Import(typeof(InvalidCastException)));
2087
internal override MethodBase LinkMethod(MethodWrapper mw)
2089
return ((RemappedMethodBaseWrapper)mw).DoLink();
2092
internal override TypeWrapper DeclaringTypeWrapper
2096
// at the moment we don't support nested remapped types
2101
internal override void Finish()
2103
if(BaseTypeWrapper != null)
2105
BaseTypeWrapper.Finish();
2107
foreach(TypeWrapper iface in Interfaces)
2111
foreach(MethodWrapper m in GetMethods())
2115
foreach(FieldWrapper f in GetFields())
2121
internal override TypeWrapper[] InnerClasses
2125
return TypeWrapper.EmptyArray;
2129
internal override TypeWrapper[] Interfaces
2133
return interfaceWrappers;
2137
internal override Type TypeAsTBD
2145
internal override Type TypeAsBaseType
2153
internal override bool IsMapUnsafeException
2157
// any remapped exceptions are automatically unsafe
2158
return shadowType == Types.Exception || shadowType.IsSubclassOf(Types.Exception);
2162
internal override bool IsFastClassLiteralSafe
2164
get { return true; }
2168
internal static void AddDeclaredExceptions(MethodBuilder mb, IKVM.Internal.MapXml.Throws[] throws)
2172
string[] exceptions = new string[throws.Length];
2173
for (int i = 0; i < exceptions.Length; i++)
2175
exceptions[i] = throws[i].Class;
2177
AttributeHelper.SetThrowsAttribute(mb, exceptions);
2181
internal void EmitRemappedTypes()
2183
Tracer.Info(Tracer.Compiler, "Emit remapped types");
2185
assemblyAttributes = map.assembly.Attributes;
2187
if(map.assembly.Classes != null)
2189
// 1st pass, put all types in remapped to make them loadable
2190
bool hasRemappedTypes = false;
2191
foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
2193
if(c.Shadows != null)
2195
remapped.Add(c.Name, new RemapperTypeWrapper(this, c, map));
2196
hasRemappedTypes = true;
2200
if(hasRemappedTypes)
2203
foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
2205
if(c.Shadows != null)
2207
remapped[c.Name].LoadInterfaces(c);
2214
internal void EmitRemappedTypes2ndPass()
2216
if (map != null && map.assembly != null && map.assembly.Classes != null)
2218
// 2nd pass, resolve interfaces, publish methods/fields
2219
foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
2221
if(c.Shadows != null)
2223
RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)remapped[c.Name];
2224
typeWrapper.Process2ndPassStep1();
2227
foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
2229
if(c.Shadows != null)
2231
RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)remapped[c.Name];
2232
typeWrapper.Process2ndPassStep2(map);
2238
internal bool IsMapUnsafeException(TypeWrapper tw)
2240
if(mappedExceptions != null)
2242
for(int i = 0; i < mappedExceptions.Length; i++)
2244
if(mappedExceptions[i].IsSubTypeOf(tw) ||
2245
(mappedExceptionsAllSubClasses[i] && tw.IsSubTypeOf(mappedExceptions[i])))
2254
internal void LoadMappedExceptions(IKVM.Internal.MapXml.Root map)
2256
if(map.exceptionMappings != null)
2258
mappedExceptionsAllSubClasses = new bool[map.exceptionMappings.Length];
2259
mappedExceptions = new TypeWrapper[map.exceptionMappings.Length];
2260
for(int i = 0; i < mappedExceptions.Length; i++)
2262
string dst = map.exceptionMappings[i].dst;
2265
mappedExceptionsAllSubClasses[i] = true;
2266
dst = dst.Substring(1);
2268
mappedExceptions[i] = LoadClassByDottedName(dst);
2270
// HACK we need to find the <exceptionMapping /> element and bind it
2271
foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
2273
if(c.Methods != null)
2275
foreach(IKVM.Internal.MapXml.Method m in c.Methods)
2277
if(m.body != null && m.body.invoke != null)
2279
foreach(IKVM.Internal.MapXml.Instruction instr in m.body.invoke)
2281
IKVM.Internal.MapXml.EmitExceptionMapping eem = instr as IKVM.Internal.MapXml.EmitExceptionMapping;
2284
eem.mapping = map.exceptionMappings;
2294
internal sealed class ExceptionMapEmitter
2296
private IKVM.Internal.MapXml.ExceptionMapping[] map;
2298
internal ExceptionMapEmitter(IKVM.Internal.MapXml.ExceptionMapping[] map)
2303
internal void Emit(IKVM.Internal.MapXml.CodeGenContext context, CodeEmitter ilgen)
2305
MethodWrapper mwSuppressFillInStackTrace = CoreClasses.java.lang.Throwable.Wrapper.GetMethodWrapper("__<suppressFillInStackTrace>", "()V", false);
2306
mwSuppressFillInStackTrace.Link();
2307
ilgen.Emit(OpCodes.Ldarg_0);
2308
ilgen.Emit(OpCodes.Callvirt, Compiler.getTypeMethod);
2309
for(int i = 0; i < map.Length; i++)
2311
ilgen.Emit(OpCodes.Dup);
2312
ilgen.Emit(OpCodes.Ldtoken, StaticCompiler.Universe.GetType(map[i].src, true));
2313
ilgen.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod);
2314
ilgen.Emit(OpCodes.Ceq);
2315
CodeEmitterLabel label = ilgen.DefineLabel();
2316
ilgen.EmitBrfalse(label);
2317
ilgen.Emit(OpCodes.Pop);
2318
if(map[i].code != null)
2320
ilgen.Emit(OpCodes.Ldarg_0);
2321
if(map[i].code.invoke != null)
2323
foreach(MapXml.Instruction instr in map[i].code.invoke)
2325
MapXml.NewObj newobj = instr as MapXml.NewObj;
2327
&& newobj.Class != null
2328
&& context.ClassLoader.LoadClassByDottedName(newobj.Class).IsSubTypeOf(CoreClasses.java.lang.Throwable.Wrapper))
2330
mwSuppressFillInStackTrace.EmitCall(ilgen);
2332
instr.Generate(context, ilgen);
2335
ilgen.Emit(OpCodes.Ret);
2339
TypeWrapper tw = context.ClassLoader.LoadClassByDottedName(map[i].dst);
2340
MethodWrapper mw = tw.GetMethodWrapper("<init>", "()V", false);
2342
mwSuppressFillInStackTrace.EmitCall(ilgen);
2343
mw.EmitNewobj(ilgen);
2344
ilgen.Emit(OpCodes.Ret);
2346
ilgen.MarkLabel(label);
2348
ilgen.Emit(OpCodes.Pop);
2349
ilgen.Emit(OpCodes.Ldarg_0);
2350
ilgen.Emit(OpCodes.Ret);
2354
internal void LoadMapXml()
2356
if(map.assembly.Classes != null)
2358
mapxml_Classes = new Dictionary<string, IKVM.Internal.MapXml.Class>();
2359
mapxml_MethodBodies = new Dictionary<MethodKey, IKVM.Internal.MapXml.InstructionList>();
2360
mapxml_ReplacedMethods = new Dictionary<MethodKey, IKVM.Internal.MapXml.ReplaceMethodCall[]>();
2361
mapxml_MethodPrologues = new Dictionary<MethodKey, IKVM.Internal.MapXml.InstructionList>();
2362
foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
2364
// if it is not a remapped type, it must be a container for native, patched or augmented methods
2365
if(c.Shadows == null)
2367
string className = c.Name;
2368
mapxml_Classes.Add(className, c);
2369
AddMapXmlMethods(className, c.Constructors);
2370
AddMapXmlMethods(className, c.Methods);
2371
if (c.Clinit != null)
2373
AddMapXmlMethod(className, c.Clinit);
2380
private void AddMapXmlMethods(string className, IKVM.Internal.MapXml.MethodBase[] methods)
2384
foreach(IKVM.Internal.MapXml.MethodBase method in methods)
2386
AddMapXmlMethod(className, method);
2391
private void AddMapXmlMethod(string className, IKVM.Internal.MapXml.MethodBase method)
2393
if(method.body != null)
2395
mapxml_MethodBodies.Add(method.ToMethodKey(className), method.body);
2397
if(method.ReplaceMethodCalls != null)
2399
mapxml_ReplacedMethods.Add(method.ToMethodKey(className), method.ReplaceMethodCalls);
2401
if (method.prologue != null)
2403
mapxml_MethodPrologues.Add(method.ToMethodKey(className), method.prologue);
2407
internal IKVM.Internal.MapXml.InstructionList GetMethodPrologue(MethodKey method)
2409
if(mapxml_MethodPrologues == null)
2413
IKVM.Internal.MapXml.InstructionList prologue;
2414
mapxml_MethodPrologues.TryGetValue(method, out prologue);
2418
internal IKVM.Internal.MapXml.ReplaceMethodCall[] GetReplacedMethodsFor(MethodWrapper mw)
2420
if(mapxml_ReplacedMethods == null)
2424
IKVM.Internal.MapXml.ReplaceMethodCall[] rmc;
2425
mapxml_ReplacedMethods.TryGetValue(new MethodKey(mw.DeclaringType.Name, mw.Name, mw.Signature), out rmc);
2429
internal Dictionary<string, IKVM.Internal.MapXml.Class> GetMapXmlClasses()
2431
return mapxml_Classes;
2434
internal Dictionary<MethodKey, IKVM.Internal.MapXml.InstructionList> GetMapXmlMethodBodies()
2436
return mapxml_MethodBodies;
2439
internal IKVM.Internal.MapXml.Param[] GetXmlMapParameters(string classname, string method, string sig)
2441
if(mapxml_Classes != null)
2443
IKVM.Internal.MapXml.Class clazz;
2444
if(mapxml_Classes.TryGetValue(classname, out clazz))
2446
if(method == "<init>" && clazz.Constructors != null)
2448
for(int i = 0; i < clazz.Constructors.Length; i++)
2450
if(clazz.Constructors[i].Sig == sig)
2452
return clazz.Constructors[i].Params;
2456
else if(clazz.Methods != null)
2458
for(int i = 0; i < clazz.Methods.Length; i++)
2460
if(clazz.Methods[i].Name == method && clazz.Methods[i].Sig == sig)
2462
return clazz.Methods[i].Params;
2471
internal bool IsGhost(TypeWrapper tw)
2473
return ghosts != null && tw.IsInterface && ghosts.ContainsKey(tw.Name);
2476
private void SetupGhosts(IKVM.Internal.MapXml.Root map)
2478
ghosts = new Dictionary<string, List<TypeWrapper>>();
2480
// find the ghost interfaces
2481
foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
2483
if(c.Shadows != null && c.Interfaces != null)
2485
// NOTE we don't support interfaces that inherit from other interfaces
2486
// (actually, if they are explicitly listed it would probably work)
2487
TypeWrapper typeWrapper = GetLoadedClass(c.Name);
2488
foreach(IKVM.Internal.MapXml.Interface iface in c.Interfaces)
2490
TypeWrapper ifaceWrapper = GetLoadedClass(iface.Name);
2491
if(ifaceWrapper == null || !ifaceWrapper.TypeAsTBD.IsAssignableFrom(typeWrapper.TypeAsTBD))
2493
AddGhost(iface.Name, typeWrapper);
2498
// we manually add the array ghost interfaces
2499
TypeWrapper array = ClassLoaderWrapper.GetWrapperFromType(Types.Array);
2500
AddGhost("java.io.Serializable", array);
2501
AddGhost("java.lang.Cloneable", array);
2504
private void AddGhost(string interfaceName, TypeWrapper implementer)
2506
List<TypeWrapper> list;
2507
if(!ghosts.TryGetValue(interfaceName, out list))
2509
list = new List<TypeWrapper>();
2510
ghosts[interfaceName] = list;
2512
list.Add(implementer);
2515
internal TypeWrapper[] GetGhostImplementers(TypeWrapper wrapper)
2517
List<TypeWrapper> list;
2518
if (!ghosts.TryGetValue(wrapper.Name, out list))
2520
return TypeWrapper.EmptyArray;
2522
return list.ToArray();
2525
internal void FinishRemappedTypes()
2527
// 3rd pass, link the methods. Note that a side effect of the linking is the
2528
// twiddling with the overriders array in the base methods, so we need to do this
2529
// as a separate pass before we compile the methods
2530
foreach(RemapperTypeWrapper typeWrapper in remapped.Values)
2532
typeWrapper.Process3rdPass();
2534
// 4th pass, implement methods/fields and bake the type
2535
foreach(RemapperTypeWrapper typeWrapper in remapped.Values)
2537
typeWrapper.Process4thPass(remapped.Values);
2540
if(assemblyAttributes != null)
2542
foreach(IKVM.Internal.MapXml.Attribute attr in assemblyAttributes)
2544
AttributeHelper.SetCustomAttribute(this, assemblyBuilder, attr);
2549
private static bool IsSigned(Assembly asm)
2551
byte[] key = asm.GetName().GetPublicKey();
2552
return key != null && key.Length != 0;
2555
internal static bool IsCoreAssembly(Assembly asm)
2557
return asm.IsDefined(StaticCompiler.GetRuntimeType("IKVM.Attributes.RemappedClassAttribute"), false);
2560
private bool CheckCompilingCoreAssembly()
2562
if (map != null && map.assembly != null && map.assembly.Classes != null)
2564
foreach (IKVM.Internal.MapXml.Class c in map.assembly.Classes)
2566
if (c.Shadows != null && c.Name == "java.lang.Object")
2575
internal static int Compile(string runtimeAssembly, List<CompilerOptions> optionsList)
2579
if(runtimeAssembly == null)
2581
// we assume that the runtime is in the same directory as the compiler
2582
runtimeAssembly = Path.Combine(typeof(CompilerClassLoader).Assembly.Location, ".." + Path.DirectorySeparatorChar + "IKVM.Runtime.dll");
2584
StaticCompiler.runtimeAssembly = StaticCompiler.LoadFile(runtimeAssembly);
2585
StaticCompiler.runtimeJniAssembly = StaticCompiler.LoadFile(Path.Combine(StaticCompiler.runtimeAssembly.Location, ".." + Path.DirectorySeparatorChar + "IKVM.Runtime.JNI.dll"));
2587
catch(FileNotFoundException)
2589
if(StaticCompiler.runtimeAssembly == null)
2591
throw new FatalCompilerErrorException(Message.RuntimeNotFound);
2593
StaticCompiler.IssueMessage(Message.NoJniRuntime);
2595
Tracer.Info(Tracer.Compiler, "Loaded runtime assembly: {0}", StaticCompiler.runtimeAssembly.FullName);
2596
bool compilingCoreAssembly = false;
2597
List<CompilerClassLoader> compilers = new List<CompilerClassLoader>();
2598
foreach (CompilerOptions options in optionsList)
2600
CompilerClassLoader compiler = null;
2601
int rc = CreateCompiler(options, ref compiler, ref compilingCoreAssembly);
2606
compilers.Add(compiler);
2607
if(options.sharedclassloader != null)
2609
options.sharedclassloader.Add(compiler);
2612
foreach (CompilerClassLoader compiler1 in compilers)
2614
foreach (CompilerClassLoader compiler2 in compilers)
2616
if (compiler1 != compiler2
2617
&& (compiler1.options.crossReferenceAllPeers || (compiler1.options.peerReferences != null && Array.IndexOf(compiler1.options.peerReferences, compiler2.options.assembly) != -1)))
2619
compiler1.AddReference(compiler2);
2623
Dictionary<CompilerClassLoader, Type> mainAssemblyTypes = new Dictionary<CompilerClassLoader, Type>();
2624
foreach (CompilerClassLoader compiler in compilers)
2626
if (compiler.options.sharedclassloader != null)
2628
Type mainAssemblyType;
2629
if (!mainAssemblyTypes.TryGetValue(compiler.options.sharedclassloader[0], out mainAssemblyType))
2631
TypeBuilder tb = compiler.options.sharedclassloader[0].GetTypeWrapperFactory().ModuleBuilder.DefineType("__<MainAssembly>", TypeAttributes.NotPublic | TypeAttributes.Abstract | TypeAttributes.SpecialName);
2632
AttributeHelper.HideFromJava(tb);
2633
mainAssemblyType = tb.CreateType();
2634
mainAssemblyTypes.Add(compiler.options.sharedclassloader[0], mainAssemblyType);
2636
if (compiler.options.sharedclassloader[0] != compiler)
2638
((AssemblyBuilder)compiler.GetTypeWrapperFactory().ModuleBuilder.Assembly).__AddTypeForwarder(mainAssemblyType);
2641
compiler.CompilePass1();
2643
foreach (CompilerClassLoader compiler in compilers)
2645
compiler.CompilePass2();
2647
if (compilingCoreAssembly)
2649
RuntimeHelperTypes.Create(compilers[0]);
2651
foreach (CompilerClassLoader compiler in compilers)
2653
compiler.EmitRemappedTypes2ndPass();
2655
foreach (CompilerClassLoader compiler in compilers)
2657
int rc = compiler.CompilePass3();
2663
Tracer.Info(Tracer.Compiler, "CompilerClassLoader.Save...");
2664
foreach (CompilerClassLoader compiler in compilers)
2666
compiler.PrepareSave();
2668
if (StaticCompiler.errorCount > 0)
2672
foreach (CompilerClassLoader compiler in compilers)
2676
return StaticCompiler.errorCount == 0 ? 0 : 1;
2679
private static int CreateCompiler(CompilerOptions options, ref CompilerClassLoader loader, ref bool compilingCoreAssembly)
2681
Tracer.Info(Tracer.Compiler, "JVM.Compile path: {0}, assembly: {1}", options.path, options.assembly);
2682
AssemblyName runtimeAssemblyName = StaticCompiler.runtimeAssembly.GetName();
2683
bool allReferencesAreStrongNamed = IsSigned(StaticCompiler.runtimeAssembly);
2684
List<Assembly> references = new List<Assembly>();
2685
foreach(Assembly reference in options.references ?? new Assembly[0])
2687
references.Add(reference);
2688
allReferencesAreStrongNamed &= IsSigned(reference);
2689
Tracer.Info(Tracer.Compiler, "Loaded reference assembly: {0}", reference.FullName);
2690
// if it's an IKVM compiled assembly, make sure that it was compiled
2691
// against same version of the runtime
2692
foreach(AssemblyName asmref in reference.GetReferencedAssemblies())
2694
if(asmref.Name == runtimeAssemblyName.Name)
2696
if(IsSigned(StaticCompiler.runtimeAssembly))
2698
// TODO we really should support binding redirects here to allow different revisions to be mixed
2699
if(asmref.FullName != runtimeAssemblyName.FullName)
2701
throw new FatalCompilerErrorException(Message.RuntimeMismatch, reference.Location, runtimeAssemblyName.FullName, asmref.FullName);
2706
if(asmref.GetPublicKeyToken() != null && asmref.GetPublicKeyToken().Length != 0)
2708
throw new FatalCompilerErrorException(Message.RuntimeMismatch, reference.Location, runtimeAssemblyName.FullName, asmref.FullName);
2714
List<object> assemblyAnnotations = new List<object>();
2715
Dictionary<string, string> baseClasses = new Dictionary<string, string>();
2716
Tracer.Info(Tracer.Compiler, "Parsing class files");
2717
foreach(KeyValuePair<string, ClassItem> kv in options.classes)
2722
byte[] buf = kv.Value.data;
2723
f = new ClassFile(buf, 0, buf.Length, null, ClassFileParseOptions.None);
2724
if(!f.IsInterface && f.SuperClass != null)
2726
baseClasses[f.SuperClass] = f.SuperClass;
2728
// NOTE the "assembly" type in the unnamed package is a magic type
2729
// that acts as the placeholder for assembly attributes
2730
if(f.Name == "assembly" && f.Annotations != null)
2732
assemblyAnnotations.AddRange(f.Annotations);
2735
catch(ClassFormatError)
2739
if(options.mainClass == null && (options.guessFileKind || options.target != PEFileKinds.Dll))
2741
foreach(ClassFile.Method m in f.Methods)
2743
if(m.IsPublic && m.IsStatic && m.Name == "main" && m.Signature == "([Ljava.lang.String;)V")
2745
StaticCompiler.IssueMessage(Message.MainMethodFound, f.Name);
2746
options.mainClass = f.Name;
2752
Dictionary<string, ClassItem> h = new Dictionary<string, ClassItem>();
2753
// HACK remove "assembly" type that exists only as a placeholder for assembly attributes
2754
options.classes.Remove("assembly");
2755
foreach(KeyValuePair<string, ClassItem> kv in options.classes)
2757
string name = kv.Key;
2758
bool excluded = false;
2759
for(int j = 0; j < options.classesToExclude.Length; j++)
2761
if(Regex.IsMatch(name, options.classesToExclude[j]))
2767
if(h.ContainsKey(name))
2769
StaticCompiler.IssueMessage(Message.DuplicateClassName, name);
2777
options.classes = null;
2779
if(options.guessFileKind && options.mainClass == null)
2781
options.target = PEFileKinds.Dll;
2784
if(options.target == PEFileKinds.Dll && options.mainClass != null)
2786
throw new FatalCompilerErrorException(Message.MainClassRequiresExe);
2789
if(options.target != PEFileKinds.Dll && options.mainClass == null)
2791
throw new FatalCompilerErrorException(Message.ExeRequiresMainClass);
2794
if(options.target == PEFileKinds.Dll && options.props.Count != 0)
2796
throw new FatalCompilerErrorException(Message.PropertiesRequireExe);
2799
if(options.path == null)
2801
if(options.target == PEFileKinds.Dll)
2803
if(options.targetIsModule)
2805
options.path = options.assembly + ".netmodule";
2809
options.path = options.assembly + ".dll";
2814
options.path = options.assembly + ".exe";
2816
StaticCompiler.IssueMessage(Message.OutputFileIs, options.path);
2819
if(options.targetIsModule)
2821
if(options.classLoader != null)
2823
throw new FatalCompilerErrorException(Message.ModuleCannotHaveClassLoader);
2825
// TODO if we're overwriting a user specified assembly name, we need to emit a warning
2826
options.assembly = new FileInfo(options.path).Name;
2829
Tracer.Info(Tracer.Compiler, "Constructing compiler");
2830
AssemblyClassLoader[] referencedAssemblies = new AssemblyClassLoader[references.Count];
2831
for(int i = 0; i < references.Count; i++)
2833
AssemblyClassLoader acl = AssemblyClassLoader.FromAssembly(references[i]);
2834
if (acl.MainAssembly != references[i])
2836
StaticCompiler.IssueMessage(options, Message.NonPrimaryAssemblyReference, references[i].GetName().Name, acl.MainAssembly.GetName().Name);
2838
if (Array.IndexOf(referencedAssemblies, acl) != -1)
2840
StaticCompiler.IssueMessage(options, Message.DuplicateAssemblyReference, acl.MainAssembly.FullName);
2842
referencedAssemblies[i] = acl;
2844
loader = new CompilerClassLoader(referencedAssemblies, options, options.path, options.targetIsModule, options.assembly, h);
2845
loader.baseClasses = baseClasses;
2846
loader.assemblyAnnotations = assemblyAnnotations;
2847
loader.classesToCompile = new List<string>(h.Keys);
2848
if(options.remapfile != null)
2850
Tracer.Info(Tracer.Compiler, "Loading remapped types (1) from {0}", options.remapfile);
2851
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(IKVM.Internal.MapXml.Root));
2852
ser.UnknownElement += new System.Xml.Serialization.XmlElementEventHandler(ser_UnknownElement);
2853
ser.UnknownAttribute += new System.Xml.Serialization.XmlAttributeEventHandler(ser_UnknownAttribute);
2857
fs = File.OpenRead(options.remapfile);
2861
throw new FatalCompilerErrorException(Message.ErrorReadingFile, options.remapfile, x.Message);
2865
XmlTextReader rdr = new XmlTextReader(fs);
2866
IKVM.Internal.MapXml.Root.xmlReader = rdr;
2867
IKVM.Internal.MapXml.Root map;
2870
map = (IKVM.Internal.MapXml.Root)ser.Deserialize(rdr);
2872
catch(InvalidOperationException x)
2874
throw new FatalCompilerErrorException(Message.ErrorParsingMapFile, options.remapfile, x.Message);
2876
if(!loader.ValidateAndSetMap(map))
2885
if(loader.CheckCompilingCoreAssembly())
2887
compilingCoreAssembly = true;
2888
ClassLoaderWrapper.SetBootstrapClassLoader(loader);
2891
// If we do not yet have a reference to the core assembly and we are not compiling the core assembly,
2892
// try to find the core assembly by looking at the assemblies that the runtime references
2893
if(JVM.CoreAssembly == null && !compilingCoreAssembly)
2895
foreach(AssemblyName name in StaticCompiler.runtimeAssembly.GetReferencedAssemblies())
2897
Assembly asm = null;
2900
asm = LoadReferencedAssembly(StaticCompiler.runtimeAssembly.Location + "/../" + name.Name + ".dll");
2902
catch(FileNotFoundException)
2905
if(asm != null && IsCoreAssembly(asm))
2907
JVM.CoreAssembly = asm;
2911
if(JVM.CoreAssembly == null)
2913
throw new FatalCompilerErrorException(Message.BootstrapClassesMissing);
2915
// we need to scan again for remapped types, now that we've loaded the core library
2916
ClassLoaderWrapper.LoadRemappedTypes();
2919
if(!compilingCoreAssembly)
2921
allReferencesAreStrongNamed &= IsSigned(JVM.CoreAssembly);
2922
loader.AddReference(AssemblyClassLoader.FromAssembly(JVM.CoreAssembly));
2925
if((options.keyPair != null || options.publicKey != null) && !allReferencesAreStrongNamed)
2927
throw new FatalCompilerErrorException(Message.StrongNameRequiresStrongNamedRefs);
2930
if(loader.map != null)
2932
loader.LoadMapXml();
2935
if(!compilingCoreAssembly)
2937
FakeTypes.Load(JVM.CoreAssembly);
2942
private static Assembly LoadReferencedAssembly(string r)
2944
Assembly asm = StaticCompiler.LoadFile(r);
2948
private bool IsStub(string className)
2950
// this function is needed because when using generics a type may be loaded before the stub is seen
2951
// and without this check that would cause a spurious IKVMC0109 warning
2953
if (classes.TryGetValue(className, out classdef))
2957
return new ClassFile(classdef.data, 0, classdef.data.Length, className, ClassFileParseOptions.RelaxedClassNameValidation).IKVMAssemblyAttribute != null;
2959
catch (ClassFormatError)
2966
private void CompilePass1()
2968
Tracer.Info(Tracer.Compiler, "Compiling class files (1)");
2969
if(CheckCompilingCoreAssembly())
2971
EmitRemappedTypes();
2973
// if we're compiling the core class library, generate the "fake" generic types
2974
// that represent the not-really existing types (i.e. the Java enums that represent .NET enums,
2975
// the Method interface for delegates and the Annotation annotation for custom attributes)
2976
if(map != null && CheckCompilingCoreAssembly())
2978
FakeTypes.Create(GetTypeWrapperFactory().ModuleBuilder, this);
2980
if(options.sharedclassloader != null && options.sharedclassloader[0] != this)
2982
packages = options.sharedclassloader[0].packages;
2986
packages = new Dictionary<string, string>();
2988
allwrappers = new List<TypeWrapper>();
2989
foreach(string s in classesToCompile)
2991
TypeWrapper wrapper = LoadClassByDottedNameFast(s);
2994
ClassLoaderWrapper loader = wrapper.GetClassLoader();
2997
if(!(loader is GenericClassLoader || loader is CompilerClassLoader || (importedStubTypes.ContainsKey(s) && importedStubTypes[s] == wrapper) || IsStub(s)))
2999
StaticCompiler.IssueMessage(options, Message.SkippingReferencedClass, s, ((AssemblyClassLoader)loader).GetAssembly(wrapper).FullName);
3003
int pos = wrapper.Name.LastIndexOf('.');
3006
packages[wrapper.Name.Substring(0, pos)] = "";
3008
if(options.sharedclassloader != null && options.sharedclassloader[0] != this)
3010
options.sharedclassloader[0].dynamicallyImportedTypes.Add(wrapper);
3012
allwrappers.Add(wrapper);
3017
private void CompilePass2()
3019
Tracer.Info(Tracer.Compiler, "Compiling class files (2)");
3020
foreach(TypeWrapper tw in allwrappers)
3022
DynamicTypeWrapper dtw = tw as DynamicTypeWrapper;
3030
private int CompilePass3()
3032
Tracer.Info(Tracer.Compiler, "Compiling class files (3)");
3033
if(map != null && CheckCompilingCoreAssembly())
3035
FakeTypes.Finish(this);
3037
foreach(string proxy in options.proxies)
3039
ProxyGenerator.Create(this, proxy);
3041
if(options.mainClass != null)
3043
TypeWrapper wrapper = null;
3046
wrapper = LoadClassByDottedNameFast(options.mainClass);
3048
catch(RetargetableJavaException)
3053
throw new FatalCompilerErrorException(Message.MainClassNotFound);
3055
MethodWrapper mw = wrapper.GetMethodWrapper("main", "([Ljava.lang.String;)V", false);
3056
if(mw == null || !mw.IsStatic)
3058
throw new FatalCompilerErrorException(Message.MainMethodNotFound);
3061
MethodInfo method = mw.GetMethod() as MethodInfo;
3064
throw new FatalCompilerErrorException(Message.UnsupportedMainMethod);
3066
if(!ReflectUtil.IsFromAssembly(method.DeclaringType, assemblyBuilder)
3067
&& (!method.IsPublic || !method.DeclaringType.IsPublic))
3069
throw new FatalCompilerErrorException(Message.ExternalMainNotAccessible);
3071
Type apartmentAttributeType = null;
3072
if(options.apartment == ApartmentState.STA)
3074
apartmentAttributeType = JVM.Import(typeof(STAThreadAttribute));
3076
else if(options.apartment == ApartmentState.MTA)
3078
apartmentAttributeType = JVM.Import(typeof(MTAThreadAttribute));
3080
SetMain(method, options.target, options.props, options.noglobbing, apartmentAttributeType);
3084
LoadMappedExceptions(map);
3085
Tracer.Info(Tracer.Compiler, "Loading remapped types (2)");
3086
FinishRemappedTypes();
3088
Tracer.Info(Tracer.Compiler, "Compiling class files (2)");
3089
AddResources(options.resources, options.compressedResources);
3090
if(options.externalResources != null)
3092
foreach(KeyValuePair<string, string> kv in options.externalResources)
3094
assemblyBuilder.AddResourceFile(JVM.MangleResourceName(kv.Key), kv.Value);
3097
if(options.fileversion != null)
3099
CustomAttributeBuilder filever = new CustomAttributeBuilder(JVM.Import(typeof(System.Reflection.AssemblyFileVersionAttribute)).GetConstructor(new Type[] { Types.String }), new object[] { options.fileversion });
3100
assemblyBuilder.SetCustomAttribute(filever);
3102
foreach(object[] def in assemblyAnnotations)
3104
Annotation annotation = Annotation.Load(this, def);
3105
if(annotation != null)
3107
annotation.Apply(this, assemblyBuilder, def);
3110
if(options.classLoader != null)
3112
TypeWrapper wrapper = null;
3115
wrapper = LoadClassByDottedNameFast(options.classLoader);
3117
catch(RetargetableJavaException)
3122
throw new FatalCompilerErrorException(Message.ClassLoaderNotFound);
3124
if(!wrapper.IsPublic && !ReflectUtil.IsFromAssembly(wrapper.TypeAsBaseType, assemblyBuilder))
3126
throw new FatalCompilerErrorException(Message.ClassLoaderNotAccessible);
3128
if(wrapper.IsAbstract)
3130
throw new FatalCompilerErrorException(Message.ClassLoaderIsAbstract);
3132
if(!wrapper.IsAssignableTo(ClassLoaderWrapper.LoadClassCritical("java.lang.ClassLoader")))
3134
throw new FatalCompilerErrorException(Message.ClassLoaderNotClassLoader);
3136
MethodWrapper mw = wrapper.GetMethodWrapper("<init>", "(Lcli.System.Reflection.Assembly;)V", false);
3139
throw new FatalCompilerErrorException(Message.ClassLoaderConstructorMissing);
3141
ConstructorInfo ci = JVM.LoadType(typeof(CustomAssemblyClassLoaderAttribute)).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { Types.Type }, null);
3142
assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(ci, new object[] { wrapper.TypeAsTBD }));
3143
// TODO it would be better to do this for all assemblies in a shared class loader group (because options.classloader is relevant only for the main assembly),
3144
// but since it is probably common to specify the custom assembly class loader at the group level, it hopefully won't make much difference in practice.
3145
MethodWrapper mwModuleInit = wrapper.GetMethodWrapper("InitializeModule", "(Lcli.System.Reflection.Module;)V", false);
3146
if(mwModuleInit != null && !mwModuleInit.IsStatic)
3148
MethodBuilder moduleInitializer = GetTypeWrapperFactory().ModuleBuilder.DefineGlobalMethod(".cctor", MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, null, Type.EmptyTypes);
3149
ILGenerator ilgen = moduleInitializer.GetILGenerator();
3150
ilgen.Emit(OpCodes.Ldtoken, moduleInitializer);
3151
ilgen.Emit(OpCodes.Call, JVM.Import(typeof(System.Reflection.MethodBase)).GetMethod("GetMethodFromHandle", new Type[] { JVM.Import(typeof(RuntimeMethodHandle)) }));
3152
ilgen.Emit(OpCodes.Callvirt, JVM.Import(typeof(System.Reflection.MemberInfo)).GetMethod("get_Module"));
3153
ilgen.Emit(OpCodes.Call, StaticCompiler.GetRuntimeType("IKVM.Runtime.ByteCodeHelper").GetMethod("InitializeModule"));
3154
ilgen.Emit(OpCodes.Ret);
3157
if (options.iconfile != null)
3159
assemblyBuilder.__DefineIconResource(IkvmcCompiler.ReadAllBytes(options.iconfile));
3161
if (options.manifestFile != null)
3163
assemblyBuilder.__DefineManifestResource(IkvmcCompiler.ReadAllBytes(options.manifestFile));
3165
assemblyBuilder.DefineVersionInfoResource();
3169
private static void ser_UnknownElement(object sender, System.Xml.Serialization.XmlElementEventArgs e)
3171
StaticCompiler.IssueMessage(Message.UnknownElementInMapFile, e.Element.Name, e.LineNumber.ToString(), e.LinePosition.ToString());
3174
private static void ser_UnknownAttribute(object sender, System.Xml.Serialization.XmlAttributeEventArgs e)
3176
StaticCompiler.IssueMessage(Message.UnknownAttributeInMapFile, e.Attr.Name, e.LineNumber.ToString(), e.LinePosition.ToString());
3179
private bool ValidateAndSetMap(IKVM.Internal.MapXml.Root map)
3182
if (map.assembly != null)
3184
if (map.assembly.Classes != null)
3186
foreach (IKVM.Internal.MapXml.Class c in map.assembly.Classes)
3188
if (c.Fields != null)
3190
foreach (IKVM.Internal.MapXml.Field f in c.Fields)
3192
ValidateNameSig("field", c.Name, f.Name, f.Sig, ref valid, true);
3195
if (c.Methods != null)
3197
foreach (IKVM.Internal.MapXml.Method m in c.Methods)
3199
ValidateNameSig("method", c.Name, m.Name, m.Sig, ref valid, false);
3202
if (c.Constructors != null)
3204
foreach (IKVM.Internal.MapXml.Constructor ctor in c.Constructors)
3206
ValidateNameSig("constructor", c.Name, "<init>", ctor.Sig, ref valid, false);
3209
if (c.Properties != null)
3211
foreach (IKVM.Internal.MapXml.Property prop in c.Properties)
3213
ValidateNameSig("property", c.Name, prop.Name, prop.Sig, ref valid, false);
3214
ValidatePropertyGetterSetter("getter", c.Name, prop.Name, prop.getter, ref valid);
3215
ValidatePropertyGetterSetter("setter", c.Name, prop.Name, prop.setter, ref valid);
3225
private static void ValidateNameSig(string member, string clazz, string name, string sig, ref bool valid, bool field)
3227
if (!IsValidName(name))
3230
StaticCompiler.IssueMessage(Message.InvalidMemberNameInMapFile, member, name, clazz);
3232
if (!IsValidSig(sig, field))
3235
StaticCompiler.IssueMessage(Message.InvalidMemberSignatureInMapFile, member, clazz, name, sig);
3239
private static void ValidatePropertyGetterSetter(string getterOrSetter, string clazz, string property, IKVM.Internal.MapXml.Method method, ref bool valid)
3243
if (!IsValidName(method.Name))
3246
StaticCompiler.IssueMessage(Message.InvalidPropertyNameInMapFile, getterOrSetter, clazz, property, method.Name);
3248
if (!ClassFile.IsValidMethodSig(method.Sig))
3251
StaticCompiler.IssueMessage(Message.InvalidPropertySignatureInMapFile, getterOrSetter, clazz, property, method.Sig);
3256
private static bool IsValidName(string name)
3258
return name != null && name.Length != 0;
3261
private static bool IsValidSig(string sig, bool field)
3263
return sig != null && (field ? ClassFile.IsValidFieldSig(sig) : ClassFile.IsValidMethodSig(sig));
3266
internal Type GetTypeFromReferencedAssembly(string name)
3268
foreach (AssemblyClassLoader acl in referencedAssemblies)
3270
Type type = acl.MainAssembly.GetType(name, false);
3279
internal override void IssueMessage(Message msgId, params string[] values)
3281
StaticCompiler.IssueMessage(options, msgId, values);
3284
internal bool TryEnableUnmanagedExports()
3286
// we only support -platform:x86 and -platform:x64
3287
// (currently IKVM.Reflection doesn't support unmanaged exports for ARM)
3288
if ((options.imageFileMachine == ImageFileMachine.I386 && (options.pekind & PortableExecutableKinds.Required32Bit) != 0)
3289
|| options.imageFileMachine == ImageFileMachine.AMD64)
3291
// when you add unmanaged exports, the ILOnly flag MUST NOT be set or the DLL will fail to load
3292
options.pekind &= ~PortableExecutableKinds.ILOnly;
3297
StaticCompiler.IssueMessage(options, Message.DllExportRequiresSupportedPlatform);
3305
internal byte[] data;
3306
internal string path;
3311
internal ICSharpCode.SharpZipLib.Zip.ZipEntry zipEntry;
3312
internal byte[] data;
3313
internal string jar;
3316
sealed class CompilerOptions
3318
internal string path;
3319
internal string keyfile;
3320
internal string keycontainer;
3321
internal bool delaysign;
3322
internal byte[] publicKey;
3323
internal StrongNameKeyPair keyPair;
3324
internal Version version;
3325
internal string fileversion;
3326
internal string iconfile;
3327
internal string manifestFile;
3328
internal bool targetIsModule;
3329
internal string assembly;
3330
internal string mainClass;
3331
internal ApartmentState apartment;
3332
internal PEFileKinds target;
3333
internal bool guessFileKind;
3334
internal Dictionary<string, ClassItem> classes;
3335
internal string[] unresolvedReferences; // only used during command line parsing
3336
internal Assembly[] references;
3337
internal string[] peerReferences;
3338
internal bool crossReferenceAllPeers = true;
3339
internal Dictionary<string, List<ResourceItem>> resources;
3340
internal string[] classesToExclude;
3341
internal string remapfile;
3342
internal Dictionary<string, string> props;
3343
internal bool noglobbing;
3344
internal CodeGenOptions codegenoptions;
3345
internal bool removeUnusedFields;
3346
internal bool compressedResources;
3347
internal string[] privatePackages;
3348
internal string[] publicPackages;
3349
internal string sourcepath;
3350
internal Dictionary<string, string> externalResources;
3351
internal string classLoader;
3352
internal PortableExecutableKinds pekind = PortableExecutableKinds.ILOnly;
3353
internal ImageFileMachine imageFileMachine = ImageFileMachine.I386;
3354
internal long baseAddress;
3355
internal int fileAlignment;
3356
internal bool highentropyva;
3357
internal List<CompilerClassLoader> sharedclassloader; // should *not* be deep copied in Copy(), because we want the list of all compilers that share a class loader
3358
internal Dictionary<string, string> suppressWarnings = new Dictionary<string, string>();
3359
internal Dictionary<string, string> errorWarnings = new Dictionary<string, string>(); // treat specific warnings as errors
3360
internal bool warnaserror; // treat all warnings as errors
3361
internal string writeSuppressWarningsFile;
3362
internal List<string> proxies = new List<string>();
3364
internal CompilerOptions Copy()
3366
CompilerOptions copy = (CompilerOptions)MemberwiseClone();
3367
if (classes != null)
3369
copy.classes = new Dictionary<string, ClassItem>(classes);
3371
if (resources != null)
3373
copy.resources = Copy(resources);
3377
copy.props = new Dictionary<string, string>(props);
3379
if (externalResources != null)
3381
copy.externalResources = new Dictionary<string, string>(externalResources);
3383
copy.suppressWarnings = new Dictionary<string, string>(suppressWarnings);
3384
copy.errorWarnings = new Dictionary<string, string>(errorWarnings);
3388
internal static Dictionary<string, List<ResourceItem>> Copy(Dictionary<string, List<ResourceItem>> resources)
3390
Dictionary<string, List<ResourceItem>> copy = new Dictionary<string, List<ResourceItem>>();
3391
foreach (KeyValuePair<string, List<ResourceItem>> kv in resources)
3393
copy.Add(kv.Key, new List<ResourceItem>(kv.Value));
3401
// These are the informational messages
3402
MainMethodFound = 1,
3405
MainMethodFromManifest = 4,
3406
// This is were the warnings start
3407
StartWarnings = 100,
3408
ClassNotFound = 100,
3409
ClassFormatError = 101,
3410
DuplicateClassName = 102,
3411
IllegalAccessError = 103,
3412
VerificationError = 104,
3413
NoClassDefFoundError = 105,
3414
GenericUnableToCompileError = 106,
3415
DuplicateResourceName = 107,
3416
NotAClassFile = 108,
3417
SkippingReferencedClass = 109,
3419
EmittedNoClassDefFoundError = 111,
3420
EmittedIllegalAccessError = 112,
3421
EmittedInstantiationError = 113,
3422
EmittedIncompatibleClassChangeError = 114,
3423
EmittedNoSuchFieldError = 115,
3424
EmittedAbstractMethodError = 116,
3425
EmittedNoSuchMethodError = 117,
3426
EmittedLinkageError = 118,
3427
EmittedVerificationError = 119,
3428
EmittedClassFormatError = 120,
3429
InvalidCustomAttribute = 121,
3430
IgnoredCustomAttribute = 122,
3431
AssumeAssemblyVersionMatch = 123,
3432
InvalidDirectoryInLibOptionPath = 124,
3433
InvalidDirectoryInLibEnvironmentPath = 125,
3434
LegacySearchRule = 126,
3435
AssemblyLocationIgnored = 127,
3436
InterfaceMethodCantBeInternal = 128,
3437
DllExportMustBeStaticMethod = 129,
3438
DllExportRequiresSupportedPlatform = 130,
3439
NonPrimaryAssemblyReference = 131,
3440
DuplicateAssemblyReference = 132,
3441
UnknownWarning = 999,
3442
// This is where the errors start
3444
UnableToCreateProxy = 4001,
3445
DuplicateProxy = 4002,
3446
MapXmlUnableToResolveOpCode = 4003,
3448
InputFileNotFound = 4005,
3449
UnknownFileType = 4006,
3450
UnknownElementInMapFile = 4007,
3451
UnknownAttributeInMapFile = 4008,
3452
InvalidMemberNameInMapFile = 4009,
3453
InvalidMemberSignatureInMapFile = 4010,
3454
InvalidPropertyNameInMapFile = 4011,
3455
InvalidPropertySignatureInMapFile = 4012,
3457
ResponseFileDepthExceeded = 5000,
3458
ErrorReadingFile = 5001,
3459
NoTargetsFound = 5002,
3460
FileFormatLimitationExceeded = 5003,
3461
CannotSpecifyBothKeyFileAndContainer = 5004,
3462
DelaySignRequiresKey = 5005,
3463
InvalidStrongNameKeyPair = 5006,
3464
ReferenceNotFound = 5007,
3465
OptionsMustPreceedChildLevels = 5008,
3466
UnrecognizedTargetType = 5009,
3467
UnrecognizedPlatform = 5010,
3468
UnrecognizedApartment = 5011,
3469
MissingFileSpecification = 5012,
3471
PathNotFound = 5014,
3473
InvalidOptionSyntax = 5016,
3474
ExternalResourceNotFound = 5017,
3475
ExternalResourceNameInvalid = 5018,
3476
InvalidVersionFormat = 5019,
3477
InvalidFileAlignment = 5020,
3478
ErrorWritingFile = 5021,
3479
UnrecognizedOption = 5022,
3480
NoOutputFileSpecified = 5023,
3481
SharedClassLoaderCannotBeUsedOnModuleTarget = 5024,
3482
RuntimeNotFound = 5025,
3483
MainClassRequiresExe = 5026,
3484
ExeRequiresMainClass = 5027,
3485
PropertiesRequireExe = 5028,
3486
ModuleCannotHaveClassLoader = 5029,
3487
ErrorParsingMapFile = 5030,
3488
BootstrapClassesMissing = 5031,
3489
StrongNameRequiresStrongNamedRefs = 5032,
3490
MainClassNotFound = 5033,
3491
MainMethodNotFound = 5034,
3492
UnsupportedMainMethod = 5035,
3493
ExternalMainNotAccessible = 5036,
3494
ClassLoaderNotFound = 5037,
3495
ClassLoaderNotAccessible = 5038,
3496
ClassLoaderIsAbstract = 5039,
3497
ClassLoaderNotClassLoader = 5040,
3498
ClassLoaderConstructorMissing = 5041,
3499
MapFileTypeNotFound = 5042,
3500
MapFileClassNotFound = 5043,
3501
MaximumErrorCountReached = 5044,
3502
LinkageError = 5045,
3503
RuntimeMismatch = 5046,
3504
RuntimeMismatchStrongName = 5047,
3505
CoreClassesMissing = 5048,
3506
CriticalClassNotFound = 5049,
3507
AssemblyContainsDuplicateClassNames = 5050,
3508
CallerIDRequiresHasCallerIDAnnotation = 5051,
3509
UnableToResolveInterface = 5052,
3512
static class StaticCompiler
3514
internal static readonly Universe Universe = new Universe();
3515
internal static Assembly runtimeAssembly;
3516
internal static Assembly runtimeJniAssembly;
3517
internal static CompilerOptions toplevel;
3518
internal static int errorCount;
3520
internal static Assembly Load(string assemblyString)
3522
return Universe.Load(assemblyString);
3525
internal static Assembly LoadFile(string path)
3527
return Universe.LoadFile(path);
3530
internal static Type GetRuntimeType(string name)
3532
Type type = runtimeAssembly.GetType(name);
3537
if (runtimeJniAssembly != null)
3539
return runtimeJniAssembly.GetType(name, true);
3543
throw new TypeLoadException(name);
3547
internal static Type GetTypeForMapXml(ClassLoaderWrapper loader, string name)
3549
Type type = GetType(loader, name);
3552
throw new FatalCompilerErrorException(Message.MapFileTypeNotFound, name);
3557
internal static TypeWrapper GetClassForMapXml(ClassLoaderWrapper loader, string name)
3559
TypeWrapper tw = loader.LoadClassByDottedNameFast(name);
3562
throw new FatalCompilerErrorException(Message.MapFileClassNotFound, name);
3567
internal static Type GetType(ClassLoaderWrapper loader, string name)
3569
CompilerClassLoader ccl = (CompilerClassLoader)loader;
3570
return ccl.GetTypeFromReferencedAssembly(name);
3573
internal static void IssueMessage(Message msgId, params string[] values)
3575
IssueMessage(toplevel, msgId, values);
3578
internal static void IssueMessage(CompilerOptions options, Message msgId, params string[] values)
3580
StringBuilder sb = new StringBuilder();
3581
sb.Append((int)msgId);
3582
if(values.Length > 0)
3584
sb.Append(':').Append(values[0]);
3586
string key = sb.ToString();
3587
if(options.suppressWarnings.ContainsKey(key)
3588
|| options.suppressWarnings.ContainsKey(((int)msgId).ToString()))
3592
options.suppressWarnings.Add(key, key);
3593
if(options.writeSuppressWarningsFile != null)
3595
File.AppendAllText(options.writeSuppressWarningsFile, "-nowarn:" + key + Environment.NewLine);
3600
case Message.MainMethodFound:
3601
msg = "Found main method in class \"{0}\"";
3603
case Message.OutputFileIs:
3604
msg = "Output file is \"{0}\"";
3606
case Message.AutoAddRef:
3607
msg = "Automatically adding reference to \"{0}\"";
3609
case Message.MainMethodFromManifest:
3610
msg = "Using main class \"{0}\" based on jar manifest";
3612
case Message.ClassNotFound:
3613
msg = "Class \"{0}\" not found";
3615
case Message.ClassFormatError:
3616
msg = "Unable to compile class \"{0}\"" + Environment.NewLine +
3617
" (class format error \"{1}\")";
3619
case Message.DuplicateClassName:
3620
msg = "Duplicate class name: \"{0}\"";
3622
case Message.IllegalAccessError:
3623
msg = "Unable to compile class \"{0}\"" + Environment.NewLine +
3624
" (illegal access error \"{1}\")";
3626
case Message.VerificationError:
3627
msg = "Unable to compile class \"{0}\"" + Environment.NewLine +
3628
" (verification error \"{1}\")";
3630
case Message.NoClassDefFoundError:
3631
msg = "Unable to compile class \"{0}\"" + Environment.NewLine +
3632
" (missing class \"{1}\")";
3634
case Message.GenericUnableToCompileError:
3635
msg = "Unable to compile class \"{0}\"" + Environment.NewLine +
3636
" (\"{1}\": \"{2}\")";
3638
case Message.DuplicateResourceName:
3639
msg = "Skipping resource (name clash): \"{0}\"";
3641
case Message.NotAClassFile:
3642
msg = "Not a class file \"{0}\", including it as resource" + Environment.NewLine +
3643
" (class format error \"{1}\")";
3645
case Message.SkippingReferencedClass:
3646
msg = "Skipping class: \"{0}\"" + Environment.NewLine +
3647
" (class is already available in referenced assembly \"{1}\")";
3649
case Message.NoJniRuntime:
3650
msg = "Unable to load runtime JNI assembly";
3652
case Message.EmittedNoClassDefFoundError:
3653
msg = "Emitted java.lang.NoClassDefFoundError in \"{0}\"" + Environment.NewLine +
3656
case Message.EmittedIllegalAccessError:
3657
msg = "Emitted java.lang.IllegalAccessError in \"{0}\"" + Environment.NewLine +
3660
case Message.EmittedInstantiationError:
3661
msg = "Emitted java.lang.InstantiationError in \"{0}\"" + Environment.NewLine +
3664
case Message.EmittedIncompatibleClassChangeError:
3665
msg = "Emitted java.lang.IncompatibleClassChangeError in \"{0}\"" + Environment.NewLine +
3668
case Message.EmittedNoSuchFieldError:
3669
msg = "Emitted java.lang.NoSuchFieldError in \"{0}\"" + Environment.NewLine +
3672
case Message.EmittedAbstractMethodError:
3673
msg = "Emitted java.lang.AbstractMethodError in \"{0}\"" + Environment.NewLine +
3676
case Message.EmittedNoSuchMethodError:
3677
msg = "Emitted java.lang.NoSuchMethodError in \"{0}\"" + Environment.NewLine +
3680
case Message.EmittedLinkageError:
3681
msg = "Emitted java.lang.LinkageError in \"{0}\"" + Environment.NewLine +
3684
case Message.EmittedVerificationError:
3685
msg = "Emitted java.lang.VerificationError in \"{0}\"" + Environment.NewLine +
3688
case Message.EmittedClassFormatError:
3689
msg = "Emitted java.lang.ClassFormatError in \"{0}\"" + Environment.NewLine +
3692
case Message.InvalidCustomAttribute:
3693
msg = "Error emitting \"{0}\" custom attribute" + Environment.NewLine +
3696
case Message.IgnoredCustomAttribute:
3697
msg = "Custom attribute \"{0}\" was ignored" + Environment.NewLine +
3700
case Message.AssumeAssemblyVersionMatch:
3701
msg = "Assuming assembly reference \"{0}\" matches \"{1}\", you may need to supply runtime policy";
3703
case Message.InvalidDirectoryInLibOptionPath:
3704
msg = "Directory \"{0}\" specified in -lib option is not valid";
3706
case Message.InvalidDirectoryInLibEnvironmentPath:
3707
msg = "Directory \"{0}\" specified in LIB environment is not valid";
3709
case Message.LegacySearchRule:
3710
msg = "Found assembly \"{0}\" using legacy search rule, please append '.dll' to the reference";
3712
case Message.AssemblyLocationIgnored:
3713
msg = "Assembly \"{0}\" is ignored as previously loaded assembly \"{1}\" has the same identity \"{2}\"";
3715
case Message.InterfaceMethodCantBeInternal:
3716
msg = "Ignoring @ikvm.lang.Internal annotation on interface method" + Environment.NewLine +
3717
" (\"{0}.{1}{2}\")";
3719
case Message.DllExportMustBeStaticMethod:
3720
msg = "Ignoring @ikvm.lang.DllExport annotation on non-static method" + Environment.NewLine +
3721
" (\"{0}.{1}{2}\")";
3723
case Message.DllExportRequiresSupportedPlatform:
3724
msg = "Ignoring @ikvm.lang.DllExport annotation due to unsupported target platform";
3726
case Message.NonPrimaryAssemblyReference:
3727
msg = "Referenced assembly \"{0}\" is not the primary assembly of a shared class loader group, referencing primary assembly \"{1}\" instead";
3729
case Message.DuplicateAssemblyReference:
3730
msg = "Duplicate assembly reference \"{0}\"";
3732
case Message.UnableToCreateProxy:
3733
msg = "Unable to create proxy \"{0}\"" + Environment.NewLine +
3736
case Message.DuplicateProxy:
3737
msg = "Duplicate proxy \"{0}\"";
3739
case Message.MapXmlUnableToResolveOpCode:
3740
msg = "Unable to resolve opcode in remap file: {0}";
3742
case Message.MapXmlError:
3743
msg = "Error in remap file: {0}";
3745
case Message.InputFileNotFound:
3746
msg = "Source file '{0}' not found";
3748
case Message.UnknownFileType:
3749
msg = "Unknown file type: {0}";
3751
case Message.UnknownElementInMapFile:
3752
msg = "Unknown element {0} in remap file, line {1}, column {2}";
3754
case Message.UnknownAttributeInMapFile:
3755
msg = "Unknown attribute {0} in remap file, line {1}, column {2}";
3757
case Message.InvalidMemberNameInMapFile:
3758
msg = "Invalid {0} name '{1}' in remap file in class {2}";
3760
case Message.InvalidMemberSignatureInMapFile:
3761
msg = "Invalid {0} signature '{3}' in remap file for {0} {1}.{2}";
3763
case Message.InvalidPropertyNameInMapFile:
3764
msg = "Invalid property {0} name '{3}' in remap file for property {1}.{2}";
3766
case Message.InvalidPropertySignatureInMapFile:
3767
msg = "Invalid property {0} signature '{3}' in remap file for property {1}.{2}";
3769
case Message.UnknownWarning:
3773
throw new InvalidProgramException();
3775
bool error = msgId >= Message.StartErrors
3776
|| (options.warnaserror && msgId >= Message.StartWarnings)
3777
|| options.errorWarnings.ContainsKey(key)
3778
|| options.errorWarnings.ContainsKey(((int)msgId).ToString());
3779
Console.Error.Write("{0} IKVMC{1:D4}: ", error ? "error" : msgId < Message.StartWarnings ? "note" : "warning", (int)msgId);
3780
if (error && Message.StartWarnings <= msgId && msgId < Message.StartErrors)
3782
Console.Error.Write("Warning as Error: ");
3784
Console.Error.WriteLine(msg, values);
3785
if(options != toplevel && options.path != null)
3787
Console.Error.WriteLine(" (in {0})", options.path);
3791
if (++errorCount == 100)
3793
throw new FatalCompilerErrorException(Message.MaximumErrorCountReached);
3798
internal static void LinkageError(string msg, TypeWrapper actualType, TypeWrapper expectedType, params object[] values)
3800
object[] args = new object[values.Length + 2];
3801
values.CopyTo(args, 2);
3802
args[0] = AssemblyQualifiedName(actualType);
3803
args[1] = AssemblyQualifiedName(expectedType);
3804
string str = string.Format(msg, args);
3805
if (actualType is UnloadableTypeWrapper && (expectedType is CompiledTypeWrapper || expectedType is DotNetTypeWrapper))
3807
str += string.Format("\n\t(Please add a reference to {0})", expectedType.TypeAsBaseType.Assembly.Location);
3809
throw new FatalCompilerErrorException(Message.LinkageError, str);
3812
private static string AssemblyQualifiedName(TypeWrapper tw)
3814
ClassLoaderWrapper loader = tw.GetClassLoader();
3815
AssemblyClassLoader acl = loader as AssemblyClassLoader;
3818
return tw.Name + ", " + acl.GetAssembly(tw).FullName;
3820
CompilerClassLoader ccl = loader as CompilerClassLoader;
3823
return tw.Name + ", " + ccl.GetTypeWrapperFactory().ModuleBuilder.Assembly.FullName;
3825
return tw.Name + " (unknown assembly)";