~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/ikvmc/CompilerClassLoader.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 2002-2012 Jeroen Frijters
 
3
 
 
4
  This software is provided 'as-is', without any express or implied
 
5
  warranty.  In no event will the authors be held liable for any damages
 
6
  arising from the use of this software.
 
7
 
 
8
  Permission is granted to anyone to use this software for any purpose,
 
9
  including commercial applications, and to alter it and redistribute it
 
10
  freely, subject to the following restrictions:
 
11
 
 
12
  1. The origin of this software must not be misrepresented; you must not
 
13
     claim that you wrote the original software. If you use this software
 
14
     in a product, an acknowledgment in the product documentation would be
 
15
     appreciated but is not required.
 
16
  2. Altered source versions must be plainly marked as such, and must not be
 
17
     misrepresented as being the original software.
 
18
  3. This notice may not be removed or altered from any source distribution.
 
19
 
 
20
  Jeroen Frijters
 
21
  jeroen@frijters.net
 
22
  
 
23
*/
 
24
 
 
25
using System;
 
26
using IKVM.Reflection;
 
27
using IKVM.Reflection.Emit;
 
28
using Type = IKVM.Reflection.Type;
 
29
using System.Resources;
 
30
using System.IO;
 
31
using System.Collections.Generic;
 
32
using System.Xml;
 
33
using System.Diagnostics;
 
34
using System.Text.RegularExpressions;
 
35
using System.Text;
 
36
using System.Threading;
 
37
using IKVM.Attributes;
 
38
 
 
39
using System.Security.Permissions;
 
40
using System.Security;
 
41
using System.Runtime.CompilerServices;
 
42
 
 
43
namespace IKVM.Internal
 
44
{
 
45
        sealed class CompilerClassLoader : ClassLoaderWrapper
 
46
        {
 
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;
 
77
 
 
78
                internal CompilerClassLoader(AssemblyClassLoader[] referencedAssemblies, CompilerOptions options, string path, bool targetIsModule, string assemblyName, Dictionary<string, ClassItem> classes)
 
79
                        : base(options.codegenoptions, null)
 
80
                {
 
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);
 
90
                }
 
91
 
 
92
                internal bool ReserveName(string javaName)
 
93
                {
 
94
                        return !classes.ContainsKey(javaName) && GetTypeWrapperFactory().ReserveName(javaName);
 
95
                }
 
96
 
 
97
                internal void AddNameMapping(string javaName, string typeName)
 
98
                {
 
99
                        nameMappings.Add(javaName, typeName);
 
100
                }
 
101
 
 
102
                internal void AddReference(AssemblyClassLoader acl)
 
103
                {
 
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;
 
108
                }
 
109
 
 
110
                internal void AddReference(CompilerClassLoader ccl)
 
111
                {
 
112
                        peerReferences.Add(ccl);
 
113
                }
 
114
 
 
115
                internal AssemblyName GetAssemblyName()
 
116
                {
 
117
                        return assemblyBuilder.GetName();
 
118
                }
 
119
 
 
120
                private static PermissionSet Combine(PermissionSet p1, PermissionSet p2)
 
121
                {
 
122
                        if (p1 == null)
 
123
                        {
 
124
                                return p2;
 
125
                        }
 
126
                        if (p2 == null)
 
127
                        {
 
128
                                return p1;
 
129
                        }
 
130
                        return p1.Union(p2);
 
131
                }
 
132
 
 
133
                internal ModuleBuilder CreateModuleBuilder()
 
134
                {
 
135
                        AssemblyName name = new AssemblyName();
 
136
                        name.Name = assemblyName;
 
137
                        if (options.keyPair != null)
 
138
                        {
 
139
                                name.KeyPair = options.keyPair;
 
140
                        }
 
141
                        else if (options.publicKey != null)
 
142
                        {
 
143
                                name.SetPublicKey(options.publicKey);
 
144
                        }
 
145
                        name.Version = options.version;
 
146
                        assemblyBuilder = 
 
147
                                StaticCompiler.Universe
 
148
                                        .DefineDynamicAssembly(name, AssemblyBuilderAccess.ReflectionOnly, assemblyDir);
 
149
                        ModuleBuilder moduleBuilder;
 
150
                        moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName, assemblyFile, this.EmitDebugInfo);
 
151
                        if(this.EmitStackTraceInfo)
 
152
                        {
 
153
                                AttributeHelper.SetSourceFile(moduleBuilder, null);
 
154
                        }
 
155
                        if(this.EmitDebugInfo || this.EmitStackTraceInfo)
 
156
                        {
 
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);
 
159
                        }
 
160
                        AttributeHelper.SetRuntimeCompatibilityAttribute(assemblyBuilder);
 
161
                        if(options.baseAddress != 0)
 
162
                        {
 
163
                                moduleBuilder.__ImageBase = options.baseAddress;
 
164
                        }
 
165
                        if(options.fileAlignment != 0)
 
166
                        {
 
167
                                moduleBuilder.__FileAlignment = options.fileAlignment;
 
168
                        }
 
169
                        if(options.highentropyva)
 
170
                        {
 
171
                                moduleBuilder.__DllCharacteristics |= DllCharacteristics.HighEntropyVA;
 
172
                        }
 
173
                        return moduleBuilder;
 
174
                }
 
175
 
 
176
                public override string ToString()
 
177
                {
 
178
                        return "CompilerClassLoader:" + options.assembly;
 
179
                }
 
180
 
 
181
                protected override TypeWrapper LoadClassImpl(string name, bool throwClassNotFoundException)
 
182
                {
 
183
                        foreach(AssemblyClassLoader acl in referencedAssemblies)
 
184
                        {
 
185
                                TypeWrapper tw = acl.DoLoad(name);
 
186
                                if(tw != null)
 
187
                                {
 
188
                                        return tw;
 
189
                                }
 
190
                        }
 
191
                        if(!peerLoading.ContainsKey(name))
 
192
                        {
 
193
                                peerLoading.Add(name, null);
 
194
                                try
 
195
                                {
 
196
                                        foreach(CompilerClassLoader ccl in peerReferences)
 
197
                                        {
 
198
                                                TypeWrapper tw = ccl.PeerLoad(name);
 
199
                                                if(tw != null)
 
200
                                                {
 
201
                                                        return tw;
 
202
                                                }
 
203
                                        }
 
204
                                        if(options.sharedclassloader != null && options.sharedclassloader[0] != this)
 
205
                                        {
 
206
                                                TypeWrapper tw = options.sharedclassloader[0].PeerLoad(name);
 
207
                                                if(tw != null)
 
208
                                                {
 
209
                                                        return tw;
 
210
                                                }
 
211
                                        }
 
212
                                }
 
213
                                finally
 
214
                                {
 
215
                                        peerLoading.Remove(name);
 
216
                                }
 
217
                        }
 
218
                        TypeWrapper tw1 = GetTypeWrapperCompilerHook(name);
 
219
                        if(tw1 != null)
 
220
                        {
 
221
                                return tw1;
 
222
                        }
 
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);
 
226
                        if(tw1 != null)
 
227
                        {
 
228
                                return tw1;
 
229
                        }
 
230
                        return LoadGenericClass(name);
 
231
                }
 
232
 
 
233
                private TypeWrapper PeerLoad(string name)
 
234
                {
 
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)
 
238
                        {
 
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)
 
242
                                {
 
243
                                        return tw;
 
244
                                }
 
245
                        }
 
246
                        if(options.sharedclassloader != null && options.sharedclassloader[0] == this)
 
247
                        {
 
248
                                foreach(CompilerClassLoader ccl in options.sharedclassloader)
 
249
                                {
 
250
                                        if(ccl != this)
 
251
                                        {
 
252
                                                TypeWrapper tw = ccl.PeerLoad(name);
 
253
                                                if(tw != null)
 
254
                                                {
 
255
                                                        return tw;
 
256
                                                }
 
257
                                        }
 
258
                                }
 
259
                        }
 
260
                        return null;
 
261
                }
 
262
 
 
263
                private TypeWrapper GetTypeWrapperCompilerHook(string name)
 
264
                {
 
265
                        RemapperTypeWrapper rtw;
 
266
                        if(remapped.TryGetValue(name, out rtw))
 
267
                        {
 
268
                                return rtw;
 
269
                        }
 
270
                        else
 
271
                        {
 
272
                                ClassItem classdef;
 
273
                                if(classes.TryGetValue(name, out classdef))
 
274
                                {
 
275
                                        classes.Remove(name);
 
276
                                        ClassFile f;
 
277
                                        try
 
278
                                        {
 
279
                                                ClassFileParseOptions cfp = ClassFileParseOptions.LocalVariableTable;
 
280
                                                if(this.EmitStackTraceInfo)
 
281
                                                {
 
282
                                                        cfp |= ClassFileParseOptions.LineNumberTable;
 
283
                                                }
 
284
                                                f = new ClassFile(classdef.data, 0, classdef.data.Length, name, cfp);
 
285
                                        }
 
286
                                        catch(ClassFormatError x)
 
287
                                        {
 
288
                                                StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, x.Message);
 
289
                                                return null;
 
290
                                        }
 
291
                                        if(options.removeUnusedFields)
 
292
                                        {
 
293
                                                f.RemoveUnusedFields();
 
294
                                        }
 
295
                                        if(f.IsPublic && options.privatePackages != null)
 
296
                                        {
 
297
                                                foreach(string p in options.privatePackages)
 
298
                                                {
 
299
                                                        if(f.Name.StartsWith(p))
 
300
                                                        {
 
301
                                                                f.SetInternal();
 
302
                                                                break;
 
303
                                                        }
 
304
                                                }
 
305
                                        }
 
306
                                        if(f.IsPublic && options.publicPackages != null)
 
307
                                        {
 
308
                                                bool found = false;
 
309
                                                foreach(string package in options.publicPackages)
 
310
                                                {
 
311
                                                        if(f.Name.StartsWith(package))
 
312
                                                        {
 
313
                                                                found = true;
 
314
                                                                break;
 
315
                                                        }
 
316
                                                }
 
317
                                                if(!found)
 
318
                                                {
 
319
                                                        f.SetInternal();
 
320
                                                }
 
321
                                        }
 
322
                                        if(!f.IsInterface
 
323
                                                && !f.IsAbstract
 
324
                                                && !f.IsPublic
 
325
                                                && !f.IsInternal
 
326
                                                && !f.IsFinal
 
327
                                                && !baseClasses.ContainsKey(f.Name)
 
328
                                                && !options.targetIsModule
 
329
                                                && options.sharedclassloader == null)
 
330
                                        {
 
331
                                                f.SetEffectivelyFinal();
 
332
                                        }
 
333
                                        if(f.SourceFileAttribute != null)
 
334
                                        {
 
335
                                                if(classdef.path != null)
 
336
                                                {
 
337
                                                        string sourceFile = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(classdef.path), f.SourceFileAttribute));
 
338
                                                        if(File.Exists(sourceFile))
 
339
                                                        {
 
340
                                                                f.SourcePath = sourceFile;
 
341
                                                        }
 
342
                                                }
 
343
                                                if(f.SourcePath == null)
 
344
                                                {
 
345
                                                        if (options.sourcepath != null)
 
346
                                                        {
 
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));
 
351
                                                        }
 
352
                                                        else
 
353
                                                        {
 
354
                                                                f.SourcePath = f.SourceFileAttribute;
 
355
                                                        }
 
356
                                                }
 
357
                                        }
 
358
                                        try
 
359
                                        {
 
360
                                                TypeWrapper type = DefineClass(f, null);
 
361
                                                if(f.IKVMAssemblyAttribute != null)
 
362
                                                {
 
363
                                                        importedStubTypes.Add(f.Name, type);
 
364
                                                }
 
365
                                                return type;
 
366
                                        }
 
367
                                        catch (ClassFormatError x)
 
368
                                        {
 
369
                                                StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, x.Message);
 
370
                                                return null;
 
371
                                        }
 
372
                                        catch (IllegalAccessError x)
 
373
                                        {
 
374
                                                StaticCompiler.IssueMessage(options, Message.IllegalAccessError, name, x.Message);
 
375
                                                return null;
 
376
                                        }
 
377
                                        catch (VerifyError x)
 
378
                                        {
 
379
                                                StaticCompiler.IssueMessage(options, Message.VerificationError, name, x.Message);
 
380
                                                return null;
 
381
                                        }
 
382
                                        catch (NoClassDefFoundError x)
 
383
                                        {
 
384
                                                StaticCompiler.IssueMessage(options, Message.NoClassDefFoundError, name, x.Message);
 
385
                                                return null;
 
386
                                        }
 
387
                                        catch (RetargetableJavaException x)
 
388
                                        {
 
389
                                                StaticCompiler.IssueMessage(options, Message.GenericUnableToCompileError, name, x.GetType().Name, x.Message);
 
390
                                                return null;
 
391
                                        }
 
392
                                }
 
393
                                else
 
394
                                {
 
395
                                        return null;
 
396
                                }
 
397
                        }
 
398
                }
 
399
 
 
400
                internal override Type GetGenericTypeDefinition(string name)
 
401
                {
 
402
                        foreach(AssemblyClassLoader loader in referencedAssemblies)
 
403
                        {
 
404
                                Type type = loader.GetGenericTypeDefinition(name);
 
405
                                if(type != null)
 
406
                                {
 
407
                                        return type;
 
408
                                }
 
409
                        }
 
410
                        return null;
 
411
                }
 
412
 
 
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)
 
416
                {
 
417
                        if (this == other)
 
418
                        {
 
419
                                return true;
 
420
                        }
 
421
                        CompilerClassLoader ccl = other as CompilerClassLoader;
 
422
                        if (ccl != null && options.sharedclassloader != null && options.sharedclassloader.Contains(ccl))
 
423
                        {
 
424
                                if (!internalsVisibleTo.Contains(ccl))
 
425
                                {
 
426
                                        AddInternalsVisibleToAttribute(ccl);
 
427
                                }
 
428
                                return true;
 
429
                        }
 
430
                        return false;
 
431
                }
 
432
 
 
433
                internal override bool InternalsVisibleToImpl(TypeWrapper wrapper, TypeWrapper friend)
 
434
                {
 
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))
 
439
                        {
 
440
                                return true;
 
441
                        }
 
442
                        CompilerClassLoader ccl = other as CompilerClassLoader;
 
443
                        if (ccl != null)
 
444
                        {
 
445
                                AddInternalsVisibleToAttribute(ccl);
 
446
                                return true;
 
447
                        }
 
448
                        return false;
 
449
                }
 
450
 
 
451
                private void AddInternalsVisibleToAttribute(CompilerClassLoader ccl)
 
452
                {
 
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)
 
459
                        {
 
460
                                pubkey = asmName.KeyPair.PublicKey;
 
461
                        }
 
462
                        if (pubkey != null && pubkey.Length != 0)
 
463
                        {
 
464
                                StringBuilder sb = new StringBuilder(name);
 
465
                                sb.Append(", PublicKey=");
 
466
                                foreach (byte b in pubkey)
 
467
                                {
 
468
                                        sb.AppendFormat("{0:X2}", b);
 
469
                                }
 
470
                                name = sb.ToString();
 
471
                        }
 
472
                        CustomAttributeBuilder cab = new CustomAttributeBuilder(JVM.Import(typeof(InternalsVisibleToAttribute)).GetConstructor(new Type[] { Types.String }), new object[] { name });
 
473
                        this.assemblyBuilder.SetCustomAttribute(cab);
 
474
                }
 
475
 
 
476
                internal void SetMain(MethodInfo m, PEFileKinds target, Dictionary<string, string> props, bool noglobbing, Type apartmentAttributeType)
 
477
                {
 
478
                        MethodBuilder mainStub = this.GetTypeWrapperFactory().ModuleBuilder.DefineGlobalMethod("main", MethodAttributes.Public | MethodAttributes.Static, Types.Int32, new Type[] { Types.String.MakeArrayType() });
 
479
                        if(apartmentAttributeType != null)
 
480
                        {
 
481
                                mainStub.SetCustomAttribute(new CustomAttributeBuilder(apartmentAttributeType.GetConstructor(Type.EmptyTypes), new object[0]));
 
482
                        }
 
483
                        CodeEmitter ilgen = CodeEmitter.Create(mainStub);
 
484
                        CodeEmitterLocal rc = ilgen.DeclareLocal(Types.Int32);
 
485
                        TypeWrapper startupType = LoadClassByDottedName("ikvm.runtime.Startup");
 
486
                        if(props.Count > 0)
 
487
                        {
 
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)
 
490
                                {
 
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('%'))
 
495
                                        {
 
496
                                                ilgen.Emit(OpCodes.Call, JVM.Import(typeof(Environment)).GetMethod("ExpandEnvironmentVariables", new Type[] { Types.String }));
 
497
                                        }
 
498
                                        ilgen.Emit(OpCodes.Callvirt, JVM.Import(typeof(System.Collections.Generic.Dictionary<string, string>)).GetMethod("Add"));
 
499
                                }
 
500
                                startupType.GetMethodWrapper("setProperties", "(Lcli.System.Collections.IDictionary;)V", false).EmitCall(ilgen);
 
501
                        }
 
502
                        ilgen.BeginExceptionBlock();
 
503
                        startupType.GetMethodWrapper("enterMainThread", "()V", false).EmitCall(ilgen);
 
504
                        ilgen.Emit(OpCodes.Ldarg_0);
 
505
                        if (!noglobbing)
 
506
                        {
 
507
                                ilgen.Emit(OpCodes.Ldc_I4_0);
 
508
                                startupType.GetMethodWrapper("glob", "([Ljava.lang.String;I)[Ljava.lang.String;", false).EmitCall(ilgen);
 
509
                        }
 
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);
 
536
                        ilgen.DoEmit();
 
537
                        assemblyBuilder.SetEntryPoint(mainStub, target);
 
538
                }
 
539
 
 
540
                private void PrepareSave()
 
541
                {
 
542
                        ((DynamicClassLoader)this.GetTypeWrapperFactory()).FinishAll();
 
543
                }
 
544
 
 
545
                private void Save()
 
546
                {
 
547
                        ModuleBuilder mb = GetTypeWrapperFactory().ModuleBuilder;
 
548
                        if(targetIsModule)
 
549
                        {
 
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++)
 
556
                                {
 
557
                                        Type[] types = referencedAssemblies[i].MainAssembly.GetExportedTypes();
 
558
                                        if(types.Length > 0)
 
559
                                        {
 
560
                                                mb.GetTypeToken(types[0]);
 
561
                                        }
 
562
                                }
 
563
                        }
 
564
                        mb.CreateGlobalFunctions();
 
565
 
 
566
                        AddJavaModuleAttribute(mb);
 
567
 
 
568
                        // add a package list and export map
 
569
                        if(options.sharedclassloader == null || options.sharedclassloader[0] == this)
 
570
                        {
 
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).
 
577
                                if(!targetIsModule)
 
578
                                {
 
579
                                        WriteExportMap();
 
580
                                }
 
581
                        }
 
582
 
 
583
                        if(targetIsModule)
 
584
                        {
 
585
                                Tracer.Info(Tracer.Compiler, "CompilerClassLoader saving {0} in {1}", assemblyFile, assemblyDir);
 
586
                                try
 
587
                                {
 
588
                                        GetTypeWrapperFactory().ModuleBuilder.__Save(options.pekind, options.imageFileMachine);
 
589
                                }
 
590
                                catch(IOException x)
 
591
                                {
 
592
                                        throw new FatalCompilerErrorException(Message.ErrorWritingFile, GetTypeWrapperFactory().ModuleBuilder.FullyQualifiedName, x.Message);
 
593
                                }
 
594
                        }
 
595
                        else
 
596
                        {
 
597
                                Tracer.Info(Tracer.Compiler, "CompilerClassLoader saving {0} in {1}", assemblyFile, assemblyDir);
 
598
                                try
 
599
                                {
 
600
                                        assemblyBuilder.Save(assemblyFile, options.pekind, options.imageFileMachine);
 
601
                                }
 
602
                                catch(IOException x)
 
603
                                {
 
604
                                        throw new FatalCompilerErrorException(Message.ErrorWritingFile, Path.Combine(assemblyDir, assemblyFile), x.Message);
 
605
                                }
 
606
                        }
 
607
                }
 
608
 
 
609
                private void AddJavaModuleAttribute(ModuleBuilder mb)
 
610
                {
 
611
                        Type typeofJavaModuleAttribute = JVM.LoadType(typeof(JavaModuleAttribute));
 
612
                        PropertyInfo[] propInfos = new PropertyInfo[] {
 
613
                                typeofJavaModuleAttribute.GetProperty("Jars")
 
614
                        };
 
615
                        object[] propValues = new object[] {
 
616
                                jarList.ToArray()
 
617
                        };
 
618
                        if (nameMappings.Count > 0)
 
619
                        {
 
620
                                string[] list = new string[nameMappings.Count * 2];
 
621
                                int i = 0;
 
622
                                foreach (KeyValuePair<string, string> kv in nameMappings)
 
623
                                {
 
624
                                        list[i++] = kv.Key;
 
625
                                        list[i++] = kv.Value;
 
626
                                }
 
627
                                CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofJavaModuleAttribute.GetConstructor(new Type[] { JVM.Import(typeof(string[])) }), new object[] { list }, propInfos, propValues);
 
628
                                mb.SetCustomAttribute(cab);
 
629
                        }
 
630
                        else
 
631
                        {
 
632
                                CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofJavaModuleAttribute.GetConstructor(Type.EmptyTypes), new object[0], propInfos, propValues);
 
633
                                mb.SetCustomAttribute(cab);
 
634
                        }
 
635
                }
 
636
 
 
637
                private static void AddExportMapEntry(Dictionary<string, List<string>> map, CompilerClassLoader ccl, string name)
 
638
                {
 
639
                        string assemblyName = ccl.assemblyBuilder.FullName;
 
640
                        List<string> list;
 
641
                        if (!map.TryGetValue(assemblyName, out list))
 
642
                        {
 
643
                                list = new List<string>();
 
644
                                map.Add(assemblyName, list);
 
645
                        }
 
646
                        if (list != null) // if list is null, we already have a wildcard export for this assembly
 
647
                        {
 
648
                                list.Add(name);
 
649
                        }
 
650
                }
 
651
 
 
652
                private void AddWildcardExports(Dictionary<string, List<string>> exportedNamesPerAssembly)
 
653
                {
 
654
                        foreach (AssemblyClassLoader acl in referencedAssemblies)
 
655
                        {
 
656
                                exportedNamesPerAssembly[acl.MainAssembly.FullName] = null;
 
657
                        }
 
658
                }
 
659
 
 
660
                private void WriteExportMap()
 
661
                {
 
662
                        Dictionary<string, List<string>> exportedNamesPerAssembly = new Dictionary<string, List<string>>();
 
663
                        AddWildcardExports(exportedNamesPerAssembly);
 
664
                        foreach (TypeWrapper tw in dynamicallyImportedTypes)
 
665
                        {
 
666
                                AddExportMapEntry(exportedNamesPerAssembly, (CompilerClassLoader)tw.GetClassLoader(), tw.Name);
 
667
                        }
 
668
                        if (options.sharedclassloader == null)
 
669
                        {
 
670
                                foreach (CompilerClassLoader ccl in peerReferences)
 
671
                                {
 
672
                                        exportedNamesPerAssembly[ccl.assemblyBuilder.FullName] = null;
 
673
                                }
 
674
                        }
 
675
                        else
 
676
                        {
 
677
                                foreach (CompilerClassLoader ccl in options.sharedclassloader)
 
678
                                {
 
679
                                        if (ccl != this)
 
680
                                        {
 
681
                                                ccl.AddWildcardExports(exportedNamesPerAssembly);
 
682
                                                if (ccl.options.resources != null)
 
683
                                                {
 
684
                                                        foreach (string name in ccl.options.resources.Keys)
 
685
                                                        {
 
686
                                                                AddExportMapEntry(exportedNamesPerAssembly, ccl, name);
 
687
                                                        }
 
688
                                                }
 
689
                                                if (ccl.options.externalResources != null)
 
690
                                                {
 
691
                                                        foreach (string name in ccl.options.externalResources.Keys)
 
692
                                                        {
 
693
                                                                AddExportMapEntry(exportedNamesPerAssembly, ccl, name);
 
694
                                                        }
 
695
                                                }
 
696
                                        }
 
697
                                }
 
698
                        }
 
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)
 
703
                        {
 
704
                                bw.Write(kv.Key);
 
705
                                if (kv.Value == null)
 
706
                                {
 
707
                                        // wildcard export
 
708
                                        bw.Write(0);
 
709
                                }
 
710
                                else
 
711
                                {
 
712
                                        Debug.Assert(kv.Value.Count != 0);
 
713
                                        bw.Write(kv.Value.Count);
 
714
                                        foreach (string name in kv.Value)
 
715
                                        {
 
716
                                                bw.Write(JVM.PersistableHash(name));
 
717
                                        }
 
718
                                }
 
719
                        }
 
720
                        ms.Position = 0;
 
721
                        this.GetTypeWrapperFactory().ModuleBuilder.DefineManifestResource("ikvm.exports", ms, ResourceAttributes.Public);
 
722
                }
 
723
 
 
724
                internal void AddResources(Dictionary<string, List<ResourceItem>> resources, bool compressedResources)
 
725
                {
 
726
                        Tracer.Info(Tracer.Compiler, "CompilerClassLoader adding resources...");
 
727
 
 
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>>();
 
731
 
 
732
                        foreach (KeyValuePair<string, List<ResourceItem>> kv in resources)
 
733
                        {
 
734
                                foreach (ResourceItem item in kv.Value)
 
735
                                {
 
736
                                        int count = 0;
 
737
                                        string jarName = item.jar;
 
738
                                retry:
 
739
                                        Dictionary<string, ResourceItem> jar;
 
740
                                        if (!jars.TryGetValue(jarName, out jar))
 
741
                                        {
 
742
                                                jar = new Dictionary<string, ResourceItem>();
 
743
                                                jars.Add(jarName, jar);
 
744
                                        }
 
745
                                        if (jar.ContainsKey(kv.Key))
 
746
                                        {
 
747
                                                jarName = Path.GetFileNameWithoutExtension(item.jar) + "-" + (count++) + Path.GetExtension(item.jar);
 
748
                                                goto retry;
 
749
                                        }
 
750
                                        jar.Add(kv.Key, item);
 
751
                                }
 
752
                        }
 
753
 
 
754
                        foreach (KeyValuePair<string, Dictionary<string, ResourceItem>> jar in jars)
 
755
                        {
 
756
                                MemoryStream mem = new MemoryStream();
 
757
                                using (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zip = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(mem))
 
758
                                {
 
759
                                        foreach (KeyValuePair<string, ResourceItem> kv in jar.Value)
 
760
                                        {
 
761
                                                ICSharpCode.SharpZipLib.Zip.ZipEntry zipEntry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(kv.Key);
 
762
                                                if (kv.Value.zipEntry == null)
 
763
                                                {
 
764
                                                        zipEntry.CompressionMethod = ICSharpCode.SharpZipLib.Zip.CompressionMethod.Stored;
 
765
                                                }
 
766
                                                else
 
767
                                                {
 
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;
 
774
                                                }
 
775
                                                if (compressedResources || zipEntry.CompressionMethod != ICSharpCode.SharpZipLib.Zip.CompressionMethod.Stored)
 
776
                                                {
 
777
                                                        zip.SetLevel(9);
 
778
                                                        zipEntry.CompressionMethod = ICSharpCode.SharpZipLib.Zip.CompressionMethod.Deflated;
 
779
                                                }
 
780
                                                zip.PutNextEntry(zipEntry);
 
781
                                                if (kv.Value.data != null)
 
782
                                                {
 
783
                                                        zip.Write(kv.Value.data, 0, kv.Value.data.Length);
 
784
                                                }
 
785
                                                zip.CloseEntry();
 
786
                                        }
 
787
                                }
 
788
                                mem = new MemoryStream(mem.ToArray());
 
789
                                string name = jar.Key;
 
790
                                if (options.targetIsModule)
 
791
                                {
 
792
                                        name = Path.GetFileNameWithoutExtension(name) + "-" + moduleBuilder.ModuleVersionId.ToString("N") + Path.GetExtension(name);
 
793
                                }
 
794
                                jarList.Add(name);
 
795
                                moduleBuilder.DefineManifestResource(name, mem, ResourceAttributes.Public);
 
796
                        }
 
797
                }
 
798
 
 
799
                private static MethodAttributes MapMethodAccessModifiers(IKVM.Internal.MapXml.MapModifiers mod)
 
800
                {
 
801
                        const IKVM.Internal.MapXml.MapModifiers access = IKVM.Internal.MapXml.MapModifiers.Public | IKVM.Internal.MapXml.MapModifiers.Protected | IKVM.Internal.MapXml.MapModifiers.Private;
 
802
                        switch(mod & access)
 
803
                        {
 
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;
 
810
                                default:
 
811
                                        return MethodAttributes.Assembly;
 
812
                        }
 
813
                }
 
814
 
 
815
                private static FieldAttributes MapFieldAccessModifiers(IKVM.Internal.MapXml.MapModifiers mod)
 
816
                {
 
817
                        const IKVM.Internal.MapXml.MapModifiers access = IKVM.Internal.MapXml.MapModifiers.Public | IKVM.Internal.MapXml.MapModifiers.Protected | IKVM.Internal.MapXml.MapModifiers.Private;
 
818
                        switch(mod & access)
 
819
                        {
 
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;
 
826
                                default:
 
827
                                        return FieldAttributes.Assembly;
 
828
                        }
 
829
                }
 
830
 
 
831
                private sealed class RemapperTypeWrapper : TypeWrapper
 
832
                {
 
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;
 
840
 
 
841
                        internal override ClassLoaderWrapper GetClassLoader()
 
842
                        {
 
843
                                return classLoader;
 
844
                        }
 
845
 
 
846
                        internal override bool IsRemapped
 
847
                        {
 
848
                                get
 
849
                                {
 
850
                                        return true;
 
851
                                }
 
852
                        }
 
853
 
 
854
                        private static TypeWrapper GetBaseWrapper(IKVM.Internal.MapXml.Class c)
 
855
                        {
 
856
                                if((c.Modifiers & IKVM.Internal.MapXml.MapModifiers.Interface) != 0)
 
857
                                {
 
858
                                        return null;
 
859
                                }
 
860
                                if(c.Name == "java.lang.Object")
 
861
                                {
 
862
                                        return null;
 
863
                                }
 
864
                                return CoreClasses.java.lang.Object.Wrapper;
 
865
                        }
 
866
 
 
867
                        internal RemapperTypeWrapper(CompilerClassLoader classLoader, IKVM.Internal.MapXml.Class c, IKVM.Internal.MapXml.Root map)
 
868
                                : base((Modifiers)c.Modifiers, c.Name)
 
869
                        {
 
870
                                this.classLoader = classLoader;
 
871
                                this.baseTypeWrapper = GetBaseWrapper(c);
 
872
                                classDef = 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)
 
879
                                {
 
880
                                        baseInterface = baseType;
 
881
                                }
 
882
                                TypeAttributes attrs = TypeAttributes.Public;
 
883
                                if((c.Modifiers & IKVM.Internal.MapXml.MapModifiers.Interface) == 0)
 
884
                                {
 
885
                                        attrs |= TypeAttributes.Class;
 
886
                                        if(baseType.IsSealed)
 
887
                                        {
 
888
                                                baseIsSealed = true;
 
889
                                                attrs |= TypeAttributes.Abstract | TypeAttributes.Sealed;
 
890
                                        }
 
891
                                }
 
892
                                else
 
893
                                {
 
894
                                        attrs |= TypeAttributes.Interface | TypeAttributes.Abstract;
 
895
                                        baseType = null;
 
896
                                }
 
897
                                if((c.Modifiers & IKVM.Internal.MapXml.MapModifiers.Abstract) != 0)
 
898
                                {
 
899
                                        attrs |= TypeAttributes.Abstract;
 
900
                                }
 
901
                                string name = c.Name.Replace('/', '.');
 
902
                                typeBuilder = classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(name, attrs, baseIsSealed ? Types.Object : baseType);
 
903
                                if(c.Attributes != null)
 
904
                                {
 
905
                                        foreach(IKVM.Internal.MapXml.Attribute custattr in c.Attributes)
 
906
                                        {
 
907
                                                AttributeHelper.SetCustomAttribute(classLoader, typeBuilder, custattr);
 
908
                                        }
 
909
                                }
 
910
                                if(baseInterface != null)
 
911
                                {
 
912
                                        typeBuilder.AddInterfaceImplementation(baseInterface);
 
913
                                }
 
914
                                if(classLoader.EmitStackTraceInfo)
 
915
                                {
 
916
                                        AttributeHelper.SetSourceFile(typeBuilder, Path.GetFileName(classLoader.options.remapfile));
 
917
                                }
 
918
 
 
919
                                if(baseIsSealed)
 
920
                                {
 
921
                                        AttributeHelper.SetModifiers(typeBuilder, (Modifiers)c.Modifiers, false);
 
922
                                }
 
923
 
 
924
                                if(c.scope == IKVM.Internal.MapXml.Scope.Public)
 
925
                                {
 
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);
 
931
                                                
 
932
                                        AttributeHelper.SetRemappedType(typeBuilder, shadowType);
 
933
                                }
 
934
 
 
935
                                List<MethodWrapper> methods = new List<MethodWrapper>();
 
936
 
 
937
                                if(c.Constructors != null)
 
938
                                {
 
939
                                        foreach(IKVM.Internal.MapXml.Constructor m in c.Constructors)
 
940
                                        {
 
941
                                                methods.Add(new RemappedConstructorWrapper(this, m));
 
942
                                        }
 
943
                                }
 
944
 
 
945
                                if(c.Methods != null)
 
946
                                {
 
947
                                        foreach(IKVM.Internal.MapXml.Method m in c.Methods)
 
948
                                        {
 
949
                                                methods.Add(new RemappedMethodWrapper(this, m, map, false));
 
950
                                        }
 
951
                                }
 
952
                                // add methods from our super classes (e.g. Throwable should have Object's methods)
 
953
                                if(!this.IsFinal && !this.IsInterface && this.BaseTypeWrapper != null)
 
954
                                {
 
955
                                        foreach(MethodWrapper mw in BaseTypeWrapper.GetMethods())
 
956
                                        {
 
957
                                                RemappedMethodWrapper rmw = mw as RemappedMethodWrapper;
 
958
                                                if(rmw != null && (rmw.IsPublic || rmw.IsProtected))
 
959
                                                {
 
960
                                                        if(!FindMethod(methods, rmw.Name, rmw.Signature))
 
961
                                                        {
 
962
                                                                methods.Add(new RemappedMethodWrapper(this, rmw.XmlMethod, map, true));
 
963
                                                        }
 
964
                                                }
 
965
                                        }
 
966
                                }
 
967
 
 
968
                                SetMethods(methods.ToArray());
 
969
                        }
 
970
 
 
971
                        internal sealed override TypeWrapper BaseTypeWrapper
 
972
                        {
 
973
                                get { return baseTypeWrapper; }
 
974
                        }
 
975
 
 
976
                        internal void LoadInterfaces(IKVM.Internal.MapXml.Class c)
 
977
                        {
 
978
                                if (c.Interfaces != null)
 
979
                                {
 
980
                                        interfaceWrappers = new TypeWrapper[c.Interfaces.Length];
 
981
                                        for (int i = 0; i < c.Interfaces.Length; i++)
 
982
                                        {
 
983
                                                interfaceWrappers[i] = classLoader.LoadClassByDottedName(c.Interfaces[i].Name);
 
984
                                        }
 
985
                                }
 
986
                                else
 
987
                                {
 
988
                                        interfaceWrappers = TypeWrapper.EmptyArray;
 
989
                                }
 
990
                        }
 
991
 
 
992
                        private static bool FindMethod(List<MethodWrapper> methods, string name, string sig)
 
993
                        {
 
994
                                foreach(MethodWrapper mw in methods)
 
995
                                {
 
996
                                        if(mw.Name == name && mw.Signature == sig)
 
997
                                        {
 
998
                                                return true;
 
999
                                        }
 
1000
                                }
 
1001
                                return false;
 
1002
                        }
 
1003
 
 
1004
                        abstract class RemappedMethodBaseWrapper : MethodWrapper
 
1005
                        {
 
1006
                                internal RemappedMethodBaseWrapper(RemapperTypeWrapper typeWrapper, string name, string sig, Modifiers modifiers)
 
1007
                                        : base(typeWrapper, name, sig, null, null, null, modifiers, MemberFlags.None)
 
1008
                                {
 
1009
                                }
 
1010
 
 
1011
                                internal abstract MethodBase DoLink();
 
1012
 
 
1013
                                internal abstract void Finish();
 
1014
                        }
 
1015
 
 
1016
                        sealed class RemappedConstructorWrapper : RemappedMethodBaseWrapper
 
1017
                        {
 
1018
                                private IKVM.Internal.MapXml.Constructor m;
 
1019
                                private MethodBuilder mbHelper;
 
1020
 
 
1021
                                internal RemappedConstructorWrapper(RemapperTypeWrapper typeWrapper, IKVM.Internal.MapXml.Constructor m)
 
1022
                                        : base(typeWrapper, "<init>", m.Sig, (Modifiers)m.Modifiers)
 
1023
                                {
 
1024
                                        this.m = m;
 
1025
                                }
 
1026
 
 
1027
                                internal override void EmitCall(CodeEmitter ilgen)
 
1028
                                {
 
1029
                                        ilgen.Emit(OpCodes.Call, GetMethod());
 
1030
                                }
 
1031
 
 
1032
                                internal override void EmitNewobj(CodeEmitter ilgen)
 
1033
                                {
 
1034
                                        if(mbHelper != null)
 
1035
                                        {
 
1036
                                                ilgen.Emit(OpCodes.Call, mbHelper);
 
1037
                                        }
 
1038
                                        else
 
1039
                                        {
 
1040
                                                ilgen.Emit(OpCodes.Newobj, GetMethod());
 
1041
                                        }
 
1042
                                }
 
1043
 
 
1044
                                internal override MethodBase DoLink()
 
1045
                                {
 
1046
                                        MethodAttributes attr = MapMethodAccessModifiers(m.Modifiers);
 
1047
                                        RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)DeclaringType;
 
1048
                                        Type[] paramTypes = typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig);
 
1049
 
 
1050
                                        MethodBuilder cbCore = null;
 
1051
 
 
1052
                                        if(typeWrapper.shadowType.IsSealed)
 
1053
                                        {
 
1054
                                                mbHelper = typeWrapper.typeBuilder.DefineMethod("newhelper", attr | MethodAttributes.Static, CallingConventions.Standard, typeWrapper.shadowType, paramTypes);
 
1055
                                                if(m.Attributes != null)
 
1056
                                                {
 
1057
                                                        foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
 
1058
                                                        {
 
1059
                                                                AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mbHelper, custattr);
 
1060
                                                        }
 
1061
                                                }
 
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);
 
1066
                                        }
 
1067
                                        else
 
1068
                                        {
 
1069
                                                cbCore = ReflectUtil.DefineConstructor(typeWrapper.typeBuilder, attr, paramTypes);
 
1070
                                                if(m.Attributes != null)
 
1071
                                                {
 
1072
                                                        foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
 
1073
                                                        {
 
1074
                                                                AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), cbCore, custattr);
 
1075
                                                        }
 
1076
                                                }
 
1077
                                                SetParameters(DeclaringType.GetClassLoader(), cbCore, m.Params);
 
1078
                                                AddDeclaredExceptions(cbCore, m.throws);
 
1079
                                        }
 
1080
                                        return cbCore;
 
1081
                                }
 
1082
                                
 
1083
                                internal override void Finish()
 
1084
                                {
 
1085
                                        // TODO we should insert method tracing (if enabled)
 
1086
 
 
1087
                                        Type[] paramTypes = this.GetParametersForDefineMethod();
 
1088
 
 
1089
                                        MethodBuilder cbCore = GetMethod() as MethodBuilder;
 
1090
 
 
1091
                                        if(cbCore != null)
 
1092
                                        {
 
1093
                                                CodeEmitter ilgen = CodeEmitter.Create(cbCore);
 
1094
                                                // TODO we need to support ghost (and other funky?) parameter types
 
1095
                                                if(m.body != null)
 
1096
                                                {
 
1097
                                                        // TODO do we need return type conversion here?
 
1098
                                                        m.body.Emit(DeclaringType.GetClassLoader(), ilgen);
 
1099
                                                }
 
1100
                                                else
 
1101
                                                {
 
1102
                                                        ilgen.Emit(OpCodes.Ldarg_0);
 
1103
                                                        for(int i = 0; i < paramTypes.Length; i++)
 
1104
                                                        {
 
1105
                                                                ilgen.EmitLdarg(i + 1);
 
1106
                                                        }
 
1107
                                                        if(m.redirect != null)
 
1108
                                                        {
 
1109
                                                                throw new NotImplementedException();
 
1110
                                                        }
 
1111
                                                        else
 
1112
                                                        {
 
1113
                                                                ConstructorInfo baseCon = DeclaringType.TypeAsTBD.GetConstructor(paramTypes);
 
1114
                                                                if(baseCon == null)
 
1115
                                                                {
 
1116
                                                                        // TODO better error handling
 
1117
                                                                        throw new InvalidOperationException("base class constructor not found: " + DeclaringType.Name + ".<init>" + m.Sig);
 
1118
                                                                }
 
1119
                                                                ilgen.Emit(OpCodes.Call, baseCon);
 
1120
                                                        }
 
1121
                                                        ilgen.Emit(OpCodes.Ret);
 
1122
                                                }
 
1123
                                                ilgen.DoEmit();
 
1124
                                                if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo)
 
1125
                                                {
 
1126
                                                        ilgen.EmitLineNumberTable(cbCore);
 
1127
                                                }
 
1128
                                        }
 
1129
 
 
1130
                                        if(mbHelper != null)
 
1131
                                        {
 
1132
                                                CodeEmitter ilgen = CodeEmitter.Create(mbHelper);
 
1133
                                                if(m.redirect != null)
 
1134
                                                {
 
1135
                                                        m.redirect.Emit(DeclaringType.GetClassLoader(), ilgen);
 
1136
                                                }
 
1137
                                                else if(m.alternateBody != null)
 
1138
                                                {
 
1139
                                                        m.alternateBody.Emit(DeclaringType.GetClassLoader(), ilgen);
 
1140
                                                }
 
1141
                                                else if(m.body != null)
 
1142
                                                {
 
1143
                                                        // <body> doesn't make sense for helper constructors (which are actually factory methods)
 
1144
                                                        throw new InvalidOperationException();
 
1145
                                                }
 
1146
                                                else
 
1147
                                                {
 
1148
                                                        ConstructorInfo baseCon = DeclaringType.TypeAsTBD.GetConstructor(paramTypes);
 
1149
                                                        if(baseCon == null)
 
1150
                                                        {
 
1151
                                                                // TODO better error handling
 
1152
                                                                throw new InvalidOperationException("constructor not found: " + DeclaringType.Name + ".<init>" + m.Sig);
 
1153
                                                        }
 
1154
                                                        for(int i = 0; i < paramTypes.Length; i++)
 
1155
                                                        {
 
1156
                                                                ilgen.EmitLdarg(i);
 
1157
                                                        }
 
1158
                                                        ilgen.Emit(OpCodes.Newobj, baseCon);
 
1159
                                                        ilgen.Emit(OpCodes.Ret);
 
1160
                                                }
 
1161
                                                ilgen.DoEmit();
 
1162
                                                if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo)
 
1163
                                                {
 
1164
                                                        ilgen.EmitLineNumberTable(mbHelper);
 
1165
                                                }
 
1166
                                        }
 
1167
                                }
 
1168
                        }
 
1169
 
 
1170
                        sealed class RemappedMethodWrapper : RemappedMethodBaseWrapper
 
1171
                        {
 
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;
 
1177
 
 
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)
 
1180
                                {
 
1181
                                        this.m = m;
 
1182
                                        this.map = map;
 
1183
                                        this.inherited = inherited;
 
1184
                                }
 
1185
 
 
1186
                                internal IKVM.Internal.MapXml.Method XmlMethod
 
1187
                                {
 
1188
                                        get
 
1189
                                        {
 
1190
                                                return m;
 
1191
                                        }
 
1192
                                }
 
1193
 
 
1194
                                internal override void EmitCall(CodeEmitter ilgen)
 
1195
                                {
 
1196
                                        if(!IsStatic && IsFinal)
 
1197
                                        {
 
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);
 
1202
                                        }
 
1203
                                        else
 
1204
                                        {
 
1205
                                                ilgen.Emit(OpCodes.Call, (MethodInfo)GetMethod());
 
1206
                                        }
 
1207
                                }
 
1208
 
 
1209
                                internal override void EmitCallvirt(CodeEmitter ilgen)
 
1210
                                {
 
1211
                                        EmitCallvirtImpl(ilgen, this.IsProtected && !mbHelper.IsPublic);
 
1212
                                }
 
1213
 
 
1214
                                private void EmitCallvirtImpl(CodeEmitter ilgen, bool cloneOrFinalizeHack)
 
1215
                                {
 
1216
                                        if(mbHelper != null && !cloneOrFinalizeHack)
 
1217
                                        {
 
1218
                                                ilgen.Emit(OpCodes.Call, mbHelper);
 
1219
                                        }
 
1220
                                        else
 
1221
                                        {
 
1222
                                                ilgen.Emit(OpCodes.Callvirt, (MethodInfo)GetMethod());
 
1223
                                        }
 
1224
                                }
 
1225
 
 
1226
                                internal override MethodBase DoLink()
 
1227
                                {
 
1228
                                        RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)DeclaringType;
 
1229
 
 
1230
                                        if(typeWrapper.IsInterface)
 
1231
                                        {
 
1232
                                                if(m.@override == null)
 
1233
                                                {
 
1234
                                                        throw new InvalidOperationException(typeWrapper.Name + "." + m.Name + m.Sig);
 
1235
                                                }
 
1236
                                                MethodInfo interfaceMethod = typeWrapper.shadowType.GetMethod(m.@override.Name, typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig));
 
1237
                                                if(interfaceMethod == null)
 
1238
                                                {
 
1239
                                                        throw new InvalidOperationException(typeWrapper.Name + "." + m.Name + m.Sig);
 
1240
                                                }
 
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)
 
1245
                                                {
 
1246
                                                        if(c.Methods != null)
 
1247
                                                        {
 
1248
                                                                foreach(IKVM.Internal.MapXml.Method mm in c.Methods)
 
1249
                                                                {
 
1250
                                                                        if(mm.Name == m.Name && mm.Sig == m.Sig && mm.body != null)
 
1251
                                                                        {
 
1252
                                                                                if(specialCases == null)
 
1253
                                                                                {
 
1254
                                                                                        specialCases = new List<IKVM.Internal.MapXml.Class>();
 
1255
                                                                                }
 
1256
                                                                                specialCases.Add(c);
 
1257
                                                                                break;
 
1258
                                                                        }
 
1259
                                                                }
 
1260
                                                        }
 
1261
                                                }
 
1262
                                                string[] throws;
 
1263
                                                if (m.throws == null)
 
1264
                                                {
 
1265
                                                        throws = new string[0];
 
1266
                                                }
 
1267
                                                else
 
1268
                                                {
 
1269
                                                        throws = new string[m.throws.Length];
 
1270
                                                        for (int i = 0; i < throws.Length; i++)
 
1271
                                                        {
 
1272
                                                                throws[i] = m.throws[i].Class;
 
1273
                                                        }
 
1274
                                                }
 
1275
                                                AttributeHelper.SetRemappedInterfaceMethod(typeWrapper.typeBuilder, m.Name, m.@override.Name, throws);
 
1276
                                                MethodBuilder helper = null;
 
1277
                                                if(specialCases != null)
 
1278
                                                {
 
1279
                                                        CodeEmitter ilgen;
 
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)
 
1285
                                                        {
 
1286
                                                                typeWrapper.helperTypeBuilder = typeWrapper.typeBuilder.DefineNestedType("__Helper", TypeAttributes.NestedPublic | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Abstract);
 
1287
                                                                AttributeHelper.HideFromJava(typeWrapper.helperTypeBuilder);
 
1288
                                                        }
 
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)
 
1291
                                                        {
 
1292
                                                                foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
 
1293
                                                                {
 
1294
                                                                        AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), helper, custattr);
 
1295
                                                                }
 
1296
                                                        }
 
1297
                                                        SetParameters(DeclaringType.GetClassLoader(), helper, m.Params);
 
1298
                                                        ilgen = CodeEmitter.Create(helper);
 
1299
                                                        foreach(IKVM.Internal.MapXml.Class c in specialCases)
 
1300
                                                        {
 
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++)
 
1308
                                                                {
 
1309
                                                                        ilgen.EmitLdarg(i);
 
1310
                                                                }
 
1311
                                                                MethodWrapper mw = tw.GetMethodWrapper(m.Name, m.Sig, false);
 
1312
                                                                mw.Link();
 
1313
                                                                mw.EmitCallvirt(ilgen);
 
1314
                                                                ilgen.Emit(OpCodes.Ret);
 
1315
                                                                ilgen.MarkLabel(label);
 
1316
                                                                ilgen.Emit(OpCodes.Pop);
 
1317
                                                        }
 
1318
                                                        for(int i = 0; i < argTypes.Length; i++)
 
1319
                                                        {
 
1320
                                                                ilgen.EmitLdarg(i);
 
1321
                                                        }
 
1322
                                                        ilgen.Emit(OpCodes.Callvirt, interfaceMethod);
 
1323
                                                        ilgen.Emit(OpCodes.Ret);
 
1324
                                                        ilgen.DoEmit();
 
1325
                                                }
 
1326
                                                mbHelper = helper;
 
1327
                                                return interfaceMethod;
 
1328
                                        }
 
1329
                                        else
 
1330
                                        {
 
1331
                                                MethodBuilder mbCore = null;
 
1332
                                                Type[] paramTypes = typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig);
 
1333
                                                Type retType = typeWrapper.GetClassLoader().RetTypeWrapperFromSig(m.Sig).TypeAsSignatureType;
 
1334
 
 
1335
                                                if(typeWrapper.shadowType.IsSealed && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0)
 
1336
                                                {
 
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)
 
1339
                                                        {
 
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))
 
1348
                                                                {
 
1349
                                                                        baseMethod.overriders.Add(typeWrapper);
 
1350
                                                                }
 
1351
                                                        }
 
1352
                                                }
 
1353
                                                else
 
1354
                                                {
 
1355
                                                        MethodInfo overrideMethod = null;
 
1356
                                                        MethodAttributes attr = MapMethodAccessModifiers(m.Modifiers) | MethodAttributes.HideBySig;
 
1357
                                                        if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) != 0)
 
1358
                                                        {
 
1359
                                                                attr |= MethodAttributes.Static;
 
1360
                                                        }
 
1361
                                                        else if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Private) == 0 && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Final) == 0)
 
1362
                                                        {
 
1363
                                                                attr |= MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride;
 
1364
                                                                if(!typeWrapper.shadowType.IsSealed)
 
1365
                                                                {
 
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)
 
1368
                                                                        {
 
1369
                                                                                // the method we're processing is overriding a method in its shadowType (which is the actual base type)
 
1370
                                                                                attr &= ~MethodAttributes.NewSlot;
 
1371
                                                                        }
 
1372
                                                                }
 
1373
                                                                if(typeWrapper.BaseTypeWrapper != null)
 
1374
                                                                {
 
1375
                                                                        RemappedMethodWrapper baseMethod = typeWrapper.BaseTypeWrapper.GetMethodWrapper(m.Name, m.Sig, true) as RemappedMethodWrapper;
 
1376
                                                                        if(baseMethod != null)
 
1377
                                                                        {
 
1378
                                                                                baseMethod.overriders.Add(typeWrapper);
 
1379
                                                                                if(baseMethod.m.@override != null)
 
1380
                                                                                {
 
1381
                                                                                        overrideMethod = typeWrapper.BaseTypeWrapper.TypeAsTBD.GetMethod(baseMethod.m.@override.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, paramTypes, null);
 
1382
                                                                                        if(overrideMethod == null)
 
1383
                                                                                        {
 
1384
                                                                                                throw new InvalidOperationException();
 
1385
                                                                                        }
 
1386
                                                                                }
 
1387
                                                                        }
 
1388
                                                                }
 
1389
                                                        }
 
1390
                                                        mbCore = typeWrapper.typeBuilder.DefineMethod(m.Name, attr, CallingConventions.Standard, retType, paramTypes);
 
1391
                                                        if(m.Attributes != null)
 
1392
                                                        {
 
1393
                                                                foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
 
1394
                                                                {
 
1395
                                                                        AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mbCore, custattr);
 
1396
                                                                }
 
1397
                                                        }
 
1398
                                                        SetParameters(DeclaringType.GetClassLoader(), mbCore, m.Params);
 
1399
                                                        if(overrideMethod != null && !inherited)
 
1400
                                                        {
 
1401
                                                                typeWrapper.typeBuilder.DefineMethodOverride(mbCore, overrideMethod);
 
1402
                                                        }
 
1403
                                                        if(inherited)
 
1404
                                                        {
 
1405
                                                                AttributeHelper.HideFromReflection(mbCore);
 
1406
                                                        }
 
1407
                                                        AddDeclaredExceptions(mbCore, m.throws);
 
1408
                                                }
 
1409
 
 
1410
                                                if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0 && !IsHideFromJava(m))
 
1411
                                                {
 
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)
 
1417
                                                        {
 
1418
                                                                attr &= ~MethodAttributes.MemberAccessMask;
 
1419
                                                                attr |= MethodAttributes.Assembly;
 
1420
                                                        }
 
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)
 
1426
                                                        {
 
1427
                                                                foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
 
1428
                                                                {
 
1429
                                                                        AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mbHelper, custattr);
 
1430
                                                                }
 
1431
                                                        }
 
1432
                                                        IKVM.Internal.MapXml.Param[] parameters;
 
1433
                                                        if(m.Params == null)
 
1434
                                                        {
 
1435
                                                                parameters = new IKVM.Internal.MapXml.Param[1];
 
1436
                                                        }
 
1437
                                                        else
 
1438
                                                        {
 
1439
                                                                parameters = new IKVM.Internal.MapXml.Param[m.Params.Length + 1];
 
1440
                                                                m.Params.CopyTo(parameters, 1);
 
1441
                                                        }
 
1442
                                                        parameters[0] = new IKVM.Internal.MapXml.Param();
 
1443
                                                        parameters[0].Name = "this";
 
1444
                                                        SetParameters(DeclaringType.GetClassLoader(), mbHelper, parameters);
 
1445
                                                        if(!typeWrapper.IsFinal)
 
1446
                                                        {
 
1447
                                                                AttributeHelper.SetEditorBrowsableNever(mbHelper);
 
1448
                                                        }
 
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." }));
 
1453
                                                }
 
1454
                                                return mbCore;
 
1455
                                        }
 
1456
                                }
 
1457
 
 
1458
                                private static bool IsHideFromJava(IKVM.Internal.MapXml.Method m)
 
1459
                                {
 
1460
                                        if (m.Attributes != null)
 
1461
                                        {
 
1462
                                                foreach (MapXml.Attribute attr in m.Attributes)
 
1463
                                                {
 
1464
                                                        if (attr.Type == "IKVM.Attributes.HideFromJavaAttribute")
 
1465
                                                        {
 
1466
                                                                return true;
 
1467
                                                        }
 
1468
                                                }
 
1469
                                        }
 
1470
                                        return false;
 
1471
                                }
 
1472
 
 
1473
                                internal override void Finish()
 
1474
                                {
 
1475
                                        // TODO we should insert method tracing (if enabled)
 
1476
                                        Type[] paramTypes = this.GetParametersForDefineMethod();
 
1477
 
 
1478
                                        MethodBuilder mbCore = GetMethod() as MethodBuilder;
 
1479
 
 
1480
                                        // NOTE sealed types don't have instance methods (only instancehelpers)
 
1481
                                        if(mbCore != null)
 
1482
                                        {
 
1483
                                                CodeEmitter ilgen = CodeEmitter.Create(mbCore);
 
1484
                                                MethodInfo baseMethod = null;
 
1485
                                                if(m.@override != null)
 
1486
                                                {
 
1487
                                                        baseMethod = DeclaringType.TypeAsTBD.GetMethod(m.@override.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, paramTypes, null);
 
1488
                                                        if(baseMethod == null)
 
1489
                                                        {
 
1490
                                                                throw new InvalidOperationException();
 
1491
                                                        }
 
1492
                                                        ((TypeBuilder)DeclaringType.TypeAsBaseType).DefineMethodOverride(mbCore, baseMethod);
 
1493
                                                }
 
1494
                                                // TODO we need to support ghost (and other funky?) parameter types
 
1495
                                                if(m.body != null)
 
1496
                                                {
 
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)
 
1500
                                                        {
 
1501
                                                                if(instr is IKVM.Internal.MapXml.Ret)
 
1502
                                                                {
 
1503
                                                                        this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
 
1504
                                                                }
 
1505
                                                                instr.Generate(context, ilgen);
 
1506
                                                        }
 
1507
                                                }
 
1508
                                                else
 
1509
                                                {
 
1510
                                                        if(m.redirect != null && m.redirect.LineNumber != -1)
 
1511
                                                        {
 
1512
                                                                ilgen.SetLineNumber((ushort)m.redirect.LineNumber);
 
1513
                                                        }
 
1514
                                                        int thisOffset = 0;
 
1515
                                                        if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0)
 
1516
                                                        {
 
1517
                                                                thisOffset = 1;
 
1518
                                                                ilgen.Emit(OpCodes.Ldarg_0);
 
1519
                                                        }
 
1520
                                                        for(int i = 0; i < paramTypes.Length; i++)
 
1521
                                                        {
 
1522
                                                                ilgen.EmitLdarg(i + thisOffset);
 
1523
                                                        }
 
1524
                                                        if(m.redirect != null)
 
1525
                                                        {
 
1526
                                                                EmitRedirect(DeclaringType.TypeAsTBD, ilgen);
 
1527
                                                        }
 
1528
                                                        else
 
1529
                                                        {
 
1530
                                                                if(baseMethod == null)
 
1531
                                                                {
 
1532
                                                                        throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
 
1533
                                                                }
 
1534
                                                                ilgen.Emit(OpCodes.Call, baseMethod);
 
1535
                                                        }
 
1536
                                                        this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
 
1537
                                                        ilgen.Emit(OpCodes.Ret);
 
1538
                                                }
 
1539
                                                ilgen.DoEmit();
 
1540
                                                if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo)
 
1541
                                                {
 
1542
                                                        ilgen.EmitLineNumberTable(mbCore);
 
1543
                                                }
 
1544
                                        }
 
1545
 
 
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)
 
1551
                                        {
 
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)
 
1555
                                                {
 
1556
                                                        // we're going to be calling the overridden version, so we don't need the null check
 
1557
                                                }
 
1558
                                                else if(!m.NoNullCheck)
 
1559
                                                {
 
1560
                                                        ilgen.Emit(OpCodes.Ldarg_0);
 
1561
                                                        ilgen.EmitNullCheck();
 
1562
                                                }
 
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)
 
1566
                                                {
 
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++)
 
1574
                                                        {
 
1575
                                                                ilgen.EmitLdarg(i + 1);
 
1576
                                                        }
 
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);
 
1582
                                                }
 
1583
                                                foreach(RemapperTypeWrapper overrider in overriders)
 
1584
                                                {
 
1585
                                                        RemappedMethodWrapper mw = (RemappedMethodWrapper)overrider.GetMethodWrapper(Name, Signature, false);
 
1586
                                                        if(mw.m.redirect == null && mw.m.body == null && mw.m.alternateBody == null)
 
1587
                                                        {
 
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
 
1590
                                                        }
 
1591
                                                        else
 
1592
                                                        {
 
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++)
 
1599
                                                                {
 
1600
                                                                        ilgen.EmitLdarg(i + 1);
 
1601
                                                                }
 
1602
                                                                mw.Link();
 
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);
 
1608
                                                        }
 
1609
                                                }
 
1610
                                                if(m.body != null || m.alternateBody != null)
 
1611
                                                {
 
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)
 
1616
                                                        {
 
1617
                                                                if(instr is IKVM.Internal.MapXml.Ret)
 
1618
                                                                {
 
1619
                                                                        this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
 
1620
                                                                }
 
1621
                                                                instr.Generate(context, ilgen);
 
1622
                                                        }
 
1623
                                                }
 
1624
                                                else
 
1625
                                                {
 
1626
                                                        if(m.redirect != null && m.redirect.LineNumber != -1)
 
1627
                                                        {
 
1628
                                                                ilgen.SetLineNumber((ushort)m.redirect.LineNumber);
 
1629
                                                        }
 
1630
                                                        Type shadowType = ((RemapperTypeWrapper)DeclaringType).shadowType;
 
1631
                                                        for(int i = 0; i < paramTypes.Length + 1; i++)
 
1632
                                                        {
 
1633
                                                                ilgen.EmitLdarg(i);
 
1634
                                                        }
 
1635
                                                        if(m.redirect != null)
 
1636
                                                        {
 
1637
                                                                EmitRedirect(shadowType, ilgen);
 
1638
                                                        }
 
1639
                                                        else if(m.@override != null)
 
1640
                                                        {
 
1641
                                                                MethodInfo baseMethod = shadowType.GetMethod(m.@override.Name, BindingFlags.Instance | BindingFlags.Public, null, paramTypes, null);
 
1642
                                                                if(baseMethod == null)
 
1643
                                                                {
 
1644
                                                                        throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
 
1645
                                                                }
 
1646
                                                                ilgen.Emit(OpCodes.Callvirt, baseMethod);
 
1647
                                                        }
 
1648
                                                        else
 
1649
                                                        {
 
1650
                                                                RemappedMethodWrapper baseMethod = DeclaringType.BaseTypeWrapper.GetMethodWrapper(Name, Signature, true) as RemappedMethodWrapper;
 
1651
                                                                if(baseMethod == null || baseMethod.m.@override == null)
 
1652
                                                                {
 
1653
                                                                        throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
 
1654
                                                                }
 
1655
                                                                MethodInfo overrideMethod = shadowType.GetMethod(baseMethod.m.@override.Name, BindingFlags.Instance | BindingFlags.Public, null, paramTypes, null);
 
1656
                                                                if(overrideMethod == null)
 
1657
                                                                {
 
1658
                                                                        throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
 
1659
                                                                }
 
1660
                                                                ilgen.Emit(OpCodes.Callvirt, overrideMethod);
 
1661
                                                        }
 
1662
                                                        this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
 
1663
                                                        ilgen.Emit(OpCodes.Ret);
 
1664
                                                }
 
1665
                                                ilgen.DoEmit();
 
1666
                                                if(this.DeclaringType.GetClassLoader().EmitStackTraceInfo)
 
1667
                                                {
 
1668
                                                        ilgen.EmitLineNumberTable(mbHelper);
 
1669
                                                }
 
1670
                                        }
 
1671
 
 
1672
                                        // do we need a helper for non-virtual reflection invocation?
 
1673
                                        if(m.nonvirtualAlternateBody != null || (m.@override != null && overriders.Count > 0))
 
1674
                                        {
 
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)
 
1681
                                                {
 
1682
                                                        foreach(IKVM.Internal.MapXml.Attribute custattr in m.Attributes)
 
1683
                                                        {
 
1684
                                                                AttributeHelper.SetCustomAttribute(DeclaringType.GetClassLoader(), mb, custattr);
 
1685
                                                        }
 
1686
                                                }
 
1687
                                                SetParameters(DeclaringType.GetClassLoader(), mb, m.Params);
 
1688
                                                AttributeHelper.HideFromJava(mb);
 
1689
                                                CodeEmitter ilgen = CodeEmitter.Create(mb);
 
1690
                                                if(m.nonvirtualAlternateBody != null)
 
1691
                                                {
 
1692
                                                        m.nonvirtualAlternateBody.Emit(DeclaringType.GetClassLoader(), ilgen);
 
1693
                                                }
 
1694
                                                else
 
1695
                                                {
 
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)
 
1699
                                                        {
 
1700
                                                                throw new InvalidOperationException(DeclaringType.Name + "." + m.Name + m.Sig);
 
1701
                                                        }
 
1702
                                                        ilgen.Emit(OpCodes.Ldarg_0);
 
1703
                                                        for(int i = 0; i < paramTypes.Length; i++)
 
1704
                                                        {
 
1705
                                                                ilgen.EmitLdarg(i + 1);
 
1706
                                                        }
 
1707
                                                        ilgen.Emit(OpCodes.Call, baseMethod);
 
1708
                                                        ilgen.Emit(OpCodes.Ret);
 
1709
                                                }
 
1710
                                                ilgen.DoEmit();
 
1711
                                        }
 
1712
                                }
 
1713
 
 
1714
                                private void EmitRedirect(Type baseType, CodeEmitter ilgen)
 
1715
                                {
 
1716
                                        string redirName = m.redirect.Name;
 
1717
                                        string redirSig = m.redirect.Sig;
 
1718
                                        if(redirName == null)
 
1719
                                        {
 
1720
                                                redirName = m.Name;
 
1721
                                        }
 
1722
                                        if(redirSig == null)
 
1723
                                        {
 
1724
                                                redirSig = m.Sig;
 
1725
                                        }
 
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)
 
1729
                                        {
 
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);
 
1734
                                                if(mi == null)
 
1735
                                                {
 
1736
                                                        throw new InvalidOperationException();
 
1737
                                                }
 
1738
                                                ilgen.Emit(OpCodes.Call, mi);
 
1739
                                        }
 
1740
                                        else
 
1741
                                        {
 
1742
                                                TypeWrapper tw = classLoader.LoadClassByDottedName(m.redirect.Class);
 
1743
                                                MethodWrapper mw = tw.GetMethodWrapper(redirName, redirSig, false);
 
1744
                                                if(mw == null)
 
1745
                                                {
 
1746
                                                        throw new InvalidOperationException("Missing redirect method: " + tw.Name + "." + redirName + redirSig);
 
1747
                                                }
 
1748
                                                mw.Link();
 
1749
                                                mw.EmitCall(ilgen);
 
1750
                                        }
 
1751
                                }
 
1752
                        }
 
1753
 
 
1754
                        private static void SetParameters(ClassLoaderWrapper loader, MethodBuilder mb, IKVM.Internal.MapXml.Param[] parameters)
 
1755
                        {
 
1756
                                if(parameters != null)
 
1757
                                {
 
1758
                                        for(int i = 0; i < parameters.Length; i++)
 
1759
                                        {
 
1760
                                                ParameterBuilder pb = mb.DefineParameter(i + 1, ParameterAttributes.None, parameters[i].Name);
 
1761
                                                if(parameters[i].Attributes != null)
 
1762
                                                {
 
1763
                                                        for(int j = 0; j < parameters[i].Attributes.Length; j++)
 
1764
                                                        {
 
1765
                                                                AttributeHelper.SetCustomAttribute(loader, pb, parameters[i].Attributes[j]);
 
1766
                                                        }
 
1767
                                                }
 
1768
                                        }
 
1769
                                }
 
1770
                        }
 
1771
 
 
1772
                        internal void Process2ndPassStep1()
 
1773
                        {
 
1774
                                if (!shadowType.IsSealed)
 
1775
                                {
 
1776
                                        foreach (TypeWrapper ifaceTypeWrapper in interfaceWrappers)
 
1777
                                        {
 
1778
                                                typeBuilder.AddInterfaceImplementation(ifaceTypeWrapper.TypeAsBaseType);
 
1779
                                        }
 
1780
                                }
 
1781
                                AttributeHelper.SetImplementsAttribute(typeBuilder, interfaceWrappers);
 
1782
                        }
 
1783
 
 
1784
                        internal void Process2ndPassStep2(IKVM.Internal.MapXml.Root map)
 
1785
                        {
 
1786
                                IKVM.Internal.MapXml.Class c = classDef;
 
1787
                                TypeBuilder tb = typeBuilder;
 
1788
 
 
1789
                                List<FieldWrapper> fields = new List<FieldWrapper>();
 
1790
 
 
1791
                                // TODO fields should be moved to the RemapperTypeWrapper constructor as well
 
1792
                                if(c.Fields != null)
 
1793
                                {
 
1794
                                        foreach(IKVM.Internal.MapXml.Field f in c.Fields)
 
1795
                                        {
 
1796
                                                {
 
1797
                                                        FieldAttributes attr = MapFieldAccessModifiers(f.Modifiers);
 
1798
                                                        if(f.Constant != null)
 
1799
                                                        {
 
1800
                                                                attr |= FieldAttributes.Literal;
 
1801
                                                        }
 
1802
                                                        else if((f.Modifiers & IKVM.Internal.MapXml.MapModifiers.Final) != 0)
 
1803
                                                        {
 
1804
                                                                attr |= FieldAttributes.InitOnly;
 
1805
                                                        }
 
1806
                                                        if((f.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) != 0)
 
1807
                                                        {
 
1808
                                                                attr |= FieldAttributes.Static;
 
1809
                                                        }
 
1810
                                                        FieldBuilder fb = tb.DefineField(f.Name, GetClassLoader().FieldTypeWrapperFromSig(f.Sig).TypeAsSignatureType, attr);
 
1811
                                                        if(f.Attributes != null)
 
1812
                                                        {
 
1813
                                                                foreach(IKVM.Internal.MapXml.Attribute custattr in f.Attributes)
 
1814
                                                                {
 
1815
                                                                        AttributeHelper.SetCustomAttribute(classLoader, fb, custattr);
 
1816
                                                                }
 
1817
                                                        }
 
1818
                                                        object constant;
 
1819
                                                        if(f.Constant != null)
 
1820
                                                        {
 
1821
                                                                switch(f.Sig[0])
 
1822
                                                                {
 
1823
                                                                        case 'J':
 
1824
                                                                                constant = long.Parse(f.Constant);
 
1825
                                                                                break;
 
1826
                                                                        default:
 
1827
                                                                                // TODO support other types
 
1828
                                                                                throw new NotImplementedException("remapped constant field of type: " + f.Sig);
 
1829
                                                                }
 
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));
 
1832
                                                        }
 
1833
                                                        else
 
1834
                                                        {
 
1835
                                                                fields.Add(FieldWrapper.Create(this, GetClassLoader().FieldTypeWrapperFromSig(f.Sig), fb, f.Name, f.Sig, new ExModifiers((Modifiers)f.Modifiers, false)));
 
1836
                                                        }
 
1837
                                                }
 
1838
                                        }
 
1839
                                }
 
1840
                                SetFields(fields.ToArray());
 
1841
                        }
 
1842
 
 
1843
                        internal void Process3rdPass()
 
1844
                        {
 
1845
                                foreach(RemappedMethodBaseWrapper m in GetMethods())
 
1846
                                {
 
1847
                                        m.Link();
 
1848
                                }
 
1849
                        }
 
1850
 
 
1851
                        internal void Process4thPass(ICollection<RemapperTypeWrapper> remappedTypes)
 
1852
                        {
 
1853
                                foreach(RemappedMethodBaseWrapper m in GetMethods())
 
1854
                                {
 
1855
                                        m.Finish();
 
1856
                                }
 
1857
 
 
1858
                                if(classDef.Clinit != null)
 
1859
                                {
 
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);
 
1864
                                        ilgen.DoEmit();
 
1865
                                }
 
1866
 
 
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)
 
1870
                                {
 
1871
                                        foreach(IKVM.Internal.MapXml.Interface iface in classDef.Interfaces)
 
1872
                                        {
 
1873
                                                GetClassLoader().LoadClassByDottedName(iface.Name).Finish();
 
1874
                                        }
 
1875
                                }
 
1876
 
 
1877
                                CreateShadowInstanceOf(remappedTypes);
 
1878
                                CreateShadowCheckCast(remappedTypes);
 
1879
 
 
1880
                                if(!shadowType.IsInterface)
 
1881
                                {
 
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())
 
1887
                                        {
 
1888
                                                MethodBuilder mb = mw.GetMethod() as MethodBuilder;
 
1889
                                                if(mb != null)
 
1890
                                                {
 
1891
                                                        methods.Add(MakeMethodKey(mb), mb);
 
1892
                                                }
 
1893
                                        }
 
1894
                                        foreach(MethodInfo mi in typeBuilder.BaseType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy))
 
1895
                                        {
 
1896
                                                string key = MakeMethodKey(mi);
 
1897
                                                if(!methods.ContainsKey(key))
 
1898
                                                {
 
1899
                                                        ParameterInfo[] paramInfo = mi.GetParameters();
 
1900
                                                        Type[] paramTypes = new Type[paramInfo.Length];
 
1901
                                                        for(int i = 0; i < paramInfo.Length; i++)
 
1902
                                                        {
 
1903
                                                                paramTypes[i] = paramInfo[i].ParameterType;
 
1904
                                                        }
 
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++)
 
1911
                                                        {
 
1912
                                                                ilgen.EmitLdarg(i);
 
1913
                                                        }
 
1914
                                                        if(!mi.IsStatic)
 
1915
                                                        {
 
1916
                                                                ilgen.EmitLdarg(paramTypes.Length);
 
1917
                                                                ilgen.Emit(OpCodes.Callvirt, mi);
 
1918
                                                        }
 
1919
                                                        else
 
1920
                                                        {
 
1921
                                                                ilgen.Emit(OpCodes.Call, mi);
 
1922
                                                        }
 
1923
                                                        ilgen.Emit(OpCodes.Ret);
 
1924
                                                        ilgen.DoEmit();
 
1925
                                                        methods[key] = mb;
 
1926
                                                }
 
1927
                                        }
 
1928
                                        foreach(PropertyInfo pi in typeBuilder.BaseType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
 
1929
                                        {
 
1930
                                                ParameterInfo[] paramInfo = pi.GetIndexParameters();
 
1931
                                                Type[] paramTypes = new Type[paramInfo.Length];
 
1932
                                                for(int i = 0; i < paramInfo.Length; i++)
 
1933
                                                {
 
1934
                                                        paramTypes[i] = paramInfo[i].ParameterType;
 
1935
                                                }
 
1936
                                                PropertyBuilder pb = typeBuilder.DefineProperty(pi.Name, PropertyAttributes.None, pi.PropertyType, paramTypes);
 
1937
                                                if(pi.GetGetMethod() != null)
 
1938
                                                {
 
1939
                                                        pb.SetGetMethod(methods[MakeMethodKey(pi.GetGetMethod())]);
 
1940
                                                }
 
1941
                                                if(pi.GetSetMethod() != null)
 
1942
                                                {
 
1943
                                                        pb.SetSetMethod(methods[MakeMethodKey(pi.GetSetMethod())]);
 
1944
                                                }
 
1945
                                                AttributeHelper.SetEditorBrowsableNever(pb);
 
1946
                                        }
 
1947
                                }
 
1948
 
 
1949
                                typeBuilder.CreateType();
 
1950
                                if(helperTypeBuilder != null)
 
1951
                                {
 
1952
                                        helperTypeBuilder.CreateType();
 
1953
                                }
 
1954
                        }
 
1955
 
 
1956
                        private static void CopyLinkDemands(MethodBuilder mb, MethodInfo mi)
 
1957
                        {
 
1958
                                foreach (CustomAttributeData cad in CustomAttributeData.__GetDeclarativeSecurity(mi))
 
1959
                                {
 
1960
                                        if (cad.ConstructorArguments.Count == 0 || (int)cad.ConstructorArguments[0].Value == (int)SecurityAction.LinkDemand)
 
1961
                                        {
 
1962
                                                mb.__AddDeclarativeSecurity(cad.__ToBuilder());
 
1963
                                        }
 
1964
                                }
 
1965
                        }
 
1966
 
 
1967
                        private static string MakeMethodKey(MethodInfo method)
 
1968
                        {
 
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++)
 
1974
                                {
 
1975
                                        paramTypes[i] = paramInfo[i].ParameterType;
 
1976
                                        sb.Append(":").Append(paramInfo[i].ParameterType.AssemblyQualifiedName);
 
1977
                                }
 
1978
                                return sb.ToString();
 
1979
                        }
 
1980
 
 
1981
                        private void CreateShadowInstanceOf(ICollection<RemapperTypeWrapper> remappedTypes)
 
1982
                        {
 
1983
                                // FXBUG .NET 1.1 doesn't allow static methods on interfaces
 
1984
                                if(typeBuilder.IsInterface)
 
1985
                                {
 
1986
                                        return;
 
1987
                                }
 
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);
 
1993
 
 
1994
                                ilgen.Emit(OpCodes.Ldarg_0);
 
1995
                                ilgen.Emit(OpCodes.Isinst, shadowType);
 
1996
                                CodeEmitterLabel retFalse = ilgen.DefineLabel();
 
1997
                                ilgen.EmitBrfalse(retFalse);
 
1998
 
 
1999
                                if(!shadowType.IsSealed)
 
2000
                                {
 
2001
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
2002
                                        ilgen.Emit(OpCodes.Isinst, typeBuilder);
 
2003
                                        ilgen.EmitBrtrue(retFalse);
 
2004
                                }
 
2005
 
 
2006
                                if(shadowType == Types.Object)
 
2007
                                {
 
2008
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
2009
                                        ilgen.Emit(OpCodes.Isinst, Types.Array);
 
2010
                                        ilgen.EmitBrtrue(retFalse);
 
2011
                                }
 
2012
 
 
2013
                                foreach(RemapperTypeWrapper r in remappedTypes)
 
2014
                                {
 
2015
                                        if(!r.shadowType.IsInterface && r.shadowType.IsSubclassOf(shadowType))
 
2016
                                        {
 
2017
                                                ilgen.Emit(OpCodes.Ldarg_0);
 
2018
                                                ilgen.Emit(OpCodes.Isinst, r.shadowType);
 
2019
                                                ilgen.EmitBrtrue(retFalse);
 
2020
                                        }
 
2021
                                }
 
2022
                                ilgen.Emit(OpCodes.Ldc_I4_1);
 
2023
                                ilgen.Emit(OpCodes.Ret);
 
2024
 
 
2025
                                ilgen.MarkLabel(retFalse);
 
2026
                                ilgen.Emit(OpCodes.Ldc_I4_0);
 
2027
                                ilgen.Emit(OpCodes.Ret);
 
2028
 
 
2029
                                ilgen.DoEmit();
 
2030
                        }
 
2031
 
 
2032
                        private void CreateShadowCheckCast(ICollection<RemapperTypeWrapper> remappedTypes)
 
2033
                        {
 
2034
                                // FXBUG .NET 1.1 doesn't allow static methods on interfaces
 
2035
                                if(typeBuilder.IsInterface)
 
2036
                                {
 
2037
                                        return;
 
2038
                                }
 
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);
 
2044
 
 
2045
                                CodeEmitterLabel fail = ilgen.DefineLabel();
 
2046
                                bool hasfail = false;
 
2047
 
 
2048
                                if(!shadowType.IsSealed)
 
2049
                                {
 
2050
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
2051
                                        ilgen.Emit(OpCodes.Isinst, typeBuilder);
 
2052
                                        ilgen.EmitBrtrue(fail);
 
2053
                                        hasfail = true;
 
2054
                                }
 
2055
 
 
2056
                                if(shadowType == Types.Object)
 
2057
                                {
 
2058
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
2059
                                        ilgen.Emit(OpCodes.Isinst, Types.Array);
 
2060
                                        ilgen.EmitBrtrue(fail);
 
2061
                                        hasfail = true;
 
2062
                                }
 
2063
 
 
2064
                                foreach(RemapperTypeWrapper r in remappedTypes)
 
2065
                                {
 
2066
                                        if(!r.shadowType.IsInterface && r.shadowType.IsSubclassOf(shadowType))
 
2067
                                        {
 
2068
                                                ilgen.Emit(OpCodes.Ldarg_0);
 
2069
                                                ilgen.Emit(OpCodes.Isinst, r.shadowType);
 
2070
                                                ilgen.EmitBrtrue(fail);
 
2071
                                                hasfail = true;
 
2072
                                        }
 
2073
                                }
 
2074
                                ilgen.Emit(OpCodes.Ldarg_0);
 
2075
                                ilgen.EmitCastclass(shadowType);
 
2076
                                ilgen.Emit(OpCodes.Ret);
 
2077
 
 
2078
                                if(hasfail)
 
2079
                                {
 
2080
                                        ilgen.MarkLabel(fail);
 
2081
                                        ilgen.ThrowException(JVM.Import(typeof(InvalidCastException)));
 
2082
                                }
 
2083
 
 
2084
                                ilgen.DoEmit();
 
2085
                        }
 
2086
 
 
2087
                        internal override MethodBase LinkMethod(MethodWrapper mw)
 
2088
                        {
 
2089
                                return ((RemappedMethodBaseWrapper)mw).DoLink();
 
2090
                        }
 
2091
 
 
2092
                        internal override TypeWrapper DeclaringTypeWrapper
 
2093
                        {
 
2094
                                get
 
2095
                                {
 
2096
                                        // at the moment we don't support nested remapped types
 
2097
                                        return null;
 
2098
                                }
 
2099
                        }
 
2100
 
 
2101
                        internal override void Finish()
 
2102
                        {
 
2103
                                if(BaseTypeWrapper != null)
 
2104
                                {
 
2105
                                        BaseTypeWrapper.Finish();
 
2106
                                }
 
2107
                                foreach(TypeWrapper iface in Interfaces)
 
2108
                                {
 
2109
                                        iface.Finish();
 
2110
                                }
 
2111
                                foreach(MethodWrapper m in GetMethods())
 
2112
                                {
 
2113
                                        m.Link();
 
2114
                                }
 
2115
                                foreach(FieldWrapper f in GetFields())
 
2116
                                {
 
2117
                                        f.Link();
 
2118
                                }
 
2119
                        }
 
2120
 
 
2121
                        internal override TypeWrapper[] InnerClasses
 
2122
                        {
 
2123
                                get
 
2124
                                {
 
2125
                                        return TypeWrapper.EmptyArray;
 
2126
                                }
 
2127
                        }
 
2128
 
 
2129
                        internal override TypeWrapper[] Interfaces
 
2130
                        {
 
2131
                                get
 
2132
                                {
 
2133
                                        return interfaceWrappers;
 
2134
                                }
 
2135
                        }
 
2136
 
 
2137
                        internal override Type TypeAsTBD
 
2138
                        {
 
2139
                                get
 
2140
                                {
 
2141
                                        return shadowType;
 
2142
                                }
 
2143
                        }
 
2144
 
 
2145
                        internal override Type TypeAsBaseType
 
2146
                        {
 
2147
                                get
 
2148
                                {
 
2149
                                        return typeBuilder;
 
2150
                                }
 
2151
                        }
 
2152
 
 
2153
                        internal override bool IsMapUnsafeException
 
2154
                        {
 
2155
                                get
 
2156
                                {
 
2157
                                        // any remapped exceptions are automatically unsafe
 
2158
                                        return shadowType == Types.Exception || shadowType.IsSubclassOf(Types.Exception);
 
2159
                                }
 
2160
                        }
 
2161
 
 
2162
                        internal override bool IsFastClassLiteralSafe
 
2163
                        {
 
2164
                                get { return true; }
 
2165
                        }
 
2166
                }
 
2167
 
 
2168
                internal static void AddDeclaredExceptions(MethodBuilder mb, IKVM.Internal.MapXml.Throws[] throws)
 
2169
                {
 
2170
                        if (throws != null)
 
2171
                        {
 
2172
                                string[] exceptions = new string[throws.Length];
 
2173
                                for (int i = 0; i < exceptions.Length; i++)
 
2174
                                {
 
2175
                                        exceptions[i] = throws[i].Class;
 
2176
                                }
 
2177
                                AttributeHelper.SetThrowsAttribute(mb, exceptions);
 
2178
                        }
 
2179
                }
 
2180
 
 
2181
                internal void EmitRemappedTypes()
 
2182
                {
 
2183
                        Tracer.Info(Tracer.Compiler, "Emit remapped types");
 
2184
 
 
2185
                        assemblyAttributes = map.assembly.Attributes;
 
2186
 
 
2187
                        if(map.assembly.Classes != null)
 
2188
                        {
 
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)
 
2192
                                {
 
2193
                                        if(c.Shadows != null)
 
2194
                                        {
 
2195
                                                remapped.Add(c.Name, new RemapperTypeWrapper(this, c, map));
 
2196
                                                hasRemappedTypes = true;
 
2197
                                        }
 
2198
                                }
 
2199
 
 
2200
                                if(hasRemappedTypes)
 
2201
                                {
 
2202
                                        SetupGhosts(map);
 
2203
                                        foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
 
2204
                                        {
 
2205
                                                if(c.Shadows != null)
 
2206
                                                {
 
2207
                                                        remapped[c.Name].LoadInterfaces(c);
 
2208
                                                }
 
2209
                                        }
 
2210
                                }
 
2211
                        }
 
2212
                }
 
2213
 
 
2214
                internal void EmitRemappedTypes2ndPass()
 
2215
                {
 
2216
                        if (map != null && map.assembly != null && map.assembly.Classes != null)
 
2217
                        {
 
2218
                                // 2nd pass, resolve interfaces, publish methods/fields
 
2219
                                foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
 
2220
                                {
 
2221
                                        if(c.Shadows != null)
 
2222
                                        {
 
2223
                                                RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)remapped[c.Name];
 
2224
                                                typeWrapper.Process2ndPassStep1();
 
2225
                                        }
 
2226
                                }
 
2227
                                foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
 
2228
                                {
 
2229
                                        if(c.Shadows != null)
 
2230
                                        {
 
2231
                                                RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)remapped[c.Name];
 
2232
                                                typeWrapper.Process2ndPassStep2(map);
 
2233
                                        }
 
2234
                                }
 
2235
                        }
 
2236
                }
 
2237
 
 
2238
                internal bool IsMapUnsafeException(TypeWrapper tw)
 
2239
                {
 
2240
                        if(mappedExceptions != null)
 
2241
                        {
 
2242
                                for(int i = 0; i < mappedExceptions.Length; i++)
 
2243
                                {
 
2244
                                        if(mappedExceptions[i].IsSubTypeOf(tw) ||
 
2245
                                                (mappedExceptionsAllSubClasses[i] && tw.IsSubTypeOf(mappedExceptions[i])))
 
2246
                                        {
 
2247
                                                return true;
 
2248
                                        }
 
2249
                                }
 
2250
                        }
 
2251
                        return false;
 
2252
                }
 
2253
 
 
2254
                internal void LoadMappedExceptions(IKVM.Internal.MapXml.Root map)
 
2255
                {
 
2256
                        if(map.exceptionMappings != null)
 
2257
                        {
 
2258
                                mappedExceptionsAllSubClasses = new bool[map.exceptionMappings.Length];
 
2259
                                mappedExceptions = new TypeWrapper[map.exceptionMappings.Length];
 
2260
                                for(int i = 0; i < mappedExceptions.Length; i++)
 
2261
                                {
 
2262
                                        string dst = map.exceptionMappings[i].dst;
 
2263
                                        if(dst[0] == '*')
 
2264
                                        {
 
2265
                                                mappedExceptionsAllSubClasses[i] = true;
 
2266
                                                dst = dst.Substring(1);
 
2267
                                        }
 
2268
                                        mappedExceptions[i] = LoadClassByDottedName(dst);
 
2269
                                }
 
2270
                                // HACK we need to find the <exceptionMapping /> element and bind it
 
2271
                                foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
 
2272
                                {
 
2273
                                        if(c.Methods != null)
 
2274
                                        {
 
2275
                                                foreach(IKVM.Internal.MapXml.Method m in c.Methods)
 
2276
                                                {
 
2277
                                                        if(m.body != null && m.body.invoke != null)
 
2278
                                                        {
 
2279
                                                                foreach(IKVM.Internal.MapXml.Instruction instr in m.body.invoke)
 
2280
                                                                {
 
2281
                                                                        IKVM.Internal.MapXml.EmitExceptionMapping eem = instr as IKVM.Internal.MapXml.EmitExceptionMapping;
 
2282
                                                                        if(eem != null)
 
2283
                                                                        {
 
2284
                                                                                eem.mapping = map.exceptionMappings;
 
2285
                                                                        }
 
2286
                                                                }
 
2287
                                                        }
 
2288
                                                }
 
2289
                                        }
 
2290
                                }
 
2291
                        }
 
2292
                }
 
2293
 
 
2294
                internal sealed class ExceptionMapEmitter
 
2295
                {
 
2296
                        private IKVM.Internal.MapXml.ExceptionMapping[] map;
 
2297
 
 
2298
                        internal ExceptionMapEmitter(IKVM.Internal.MapXml.ExceptionMapping[] map)
 
2299
                        {
 
2300
                                this.map = map;
 
2301
                        }
 
2302
 
 
2303
                        internal void Emit(IKVM.Internal.MapXml.CodeGenContext context, CodeEmitter ilgen)
 
2304
                        {
 
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++)
 
2310
                                {
 
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)
 
2319
                                        {
 
2320
                                                ilgen.Emit(OpCodes.Ldarg_0);
 
2321
                                                if(map[i].code.invoke != null)
 
2322
                                                {
 
2323
                                                        foreach(MapXml.Instruction instr in map[i].code.invoke)
 
2324
                                                        {
 
2325
                                                                MapXml.NewObj newobj = instr as MapXml.NewObj;
 
2326
                                                                if(newobj != null
 
2327
                                                                        && newobj.Class != null
 
2328
                                                                        && context.ClassLoader.LoadClassByDottedName(newobj.Class).IsSubTypeOf(CoreClasses.java.lang.Throwable.Wrapper))
 
2329
                                                                {
 
2330
                                                                        mwSuppressFillInStackTrace.EmitCall(ilgen);
 
2331
                                                                }
 
2332
                                                                instr.Generate(context, ilgen);
 
2333
                                                        }
 
2334
                                                }
 
2335
                                                ilgen.Emit(OpCodes.Ret);
 
2336
                                        }
 
2337
                                        else
 
2338
                                        {
 
2339
                                                TypeWrapper tw = context.ClassLoader.LoadClassByDottedName(map[i].dst);
 
2340
                                                MethodWrapper mw = tw.GetMethodWrapper("<init>", "()V", false);
 
2341
                                                mw.Link();
 
2342
                                                mwSuppressFillInStackTrace.EmitCall(ilgen);
 
2343
                                                mw.EmitNewobj(ilgen);
 
2344
                                                ilgen.Emit(OpCodes.Ret);
 
2345
                                        }
 
2346
                                        ilgen.MarkLabel(label);
 
2347
                                }
 
2348
                                ilgen.Emit(OpCodes.Pop);
 
2349
                                ilgen.Emit(OpCodes.Ldarg_0);
 
2350
                                ilgen.Emit(OpCodes.Ret);
 
2351
                        }
 
2352
                }
 
2353
 
 
2354
                internal void LoadMapXml()
 
2355
                {
 
2356
                        if(map.assembly.Classes != null)
 
2357
                        {
 
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)
 
2363
                                {
 
2364
                                        // if it is not a remapped type, it must be a container for native, patched or augmented methods
 
2365
                                        if(c.Shadows == null)
 
2366
                                        {
 
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)
 
2372
                                                {
 
2373
                                                        AddMapXmlMethod(className, c.Clinit);
 
2374
                                                }
 
2375
                                        }
 
2376
                                }
 
2377
                        }
 
2378
                }
 
2379
 
 
2380
                private void AddMapXmlMethods(string className, IKVM.Internal.MapXml.MethodBase[] methods)
 
2381
                {
 
2382
                        if(methods != null)
 
2383
                        {
 
2384
                                foreach(IKVM.Internal.MapXml.MethodBase method in methods)
 
2385
                                {
 
2386
                                        AddMapXmlMethod(className, method);
 
2387
                                }
 
2388
                        }
 
2389
                }
 
2390
 
 
2391
                private void AddMapXmlMethod(string className, IKVM.Internal.MapXml.MethodBase method)
 
2392
                {
 
2393
                        if(method.body != null)
 
2394
                        {
 
2395
                                mapxml_MethodBodies.Add(method.ToMethodKey(className), method.body);
 
2396
                        }
 
2397
                        if(method.ReplaceMethodCalls != null)
 
2398
                        {
 
2399
                                mapxml_ReplacedMethods.Add(method.ToMethodKey(className), method.ReplaceMethodCalls);
 
2400
                        }
 
2401
                        if (method.prologue != null)
 
2402
                        {
 
2403
                                mapxml_MethodPrologues.Add(method.ToMethodKey(className), method.prologue);
 
2404
                        }
 
2405
                }
 
2406
 
 
2407
                internal IKVM.Internal.MapXml.InstructionList GetMethodPrologue(MethodKey method)
 
2408
                {
 
2409
                        if(mapxml_MethodPrologues == null)
 
2410
                        {
 
2411
                                return null;
 
2412
                        }
 
2413
                        IKVM.Internal.MapXml.InstructionList prologue;
 
2414
                        mapxml_MethodPrologues.TryGetValue(method, out prologue);
 
2415
                        return prologue;
 
2416
                }
 
2417
 
 
2418
                internal IKVM.Internal.MapXml.ReplaceMethodCall[] GetReplacedMethodsFor(MethodWrapper mw)
 
2419
                {
 
2420
                        if(mapxml_ReplacedMethods == null)
 
2421
                        {
 
2422
                                return null;
 
2423
                        }
 
2424
                        IKVM.Internal.MapXml.ReplaceMethodCall[] rmc;
 
2425
                        mapxml_ReplacedMethods.TryGetValue(new MethodKey(mw.DeclaringType.Name, mw.Name, mw.Signature), out rmc);
 
2426
                        return rmc;
 
2427
                }
 
2428
 
 
2429
                internal Dictionary<string, IKVM.Internal.MapXml.Class> GetMapXmlClasses()
 
2430
                {
 
2431
                        return mapxml_Classes;
 
2432
                }
 
2433
 
 
2434
                internal Dictionary<MethodKey, IKVM.Internal.MapXml.InstructionList> GetMapXmlMethodBodies()
 
2435
                {
 
2436
                        return mapxml_MethodBodies;
 
2437
                }
 
2438
 
 
2439
                internal IKVM.Internal.MapXml.Param[] GetXmlMapParameters(string classname, string method, string sig)
 
2440
                {
 
2441
                        if(mapxml_Classes != null)
 
2442
                        {
 
2443
                                IKVM.Internal.MapXml.Class clazz;
 
2444
                                if(mapxml_Classes.TryGetValue(classname, out clazz))
 
2445
                                {
 
2446
                                        if(method == "<init>" && clazz.Constructors != null)
 
2447
                                        {
 
2448
                                                for(int i = 0; i < clazz.Constructors.Length; i++)
 
2449
                                                {
 
2450
                                                        if(clazz.Constructors[i].Sig == sig)
 
2451
                                                        {
 
2452
                                                                return clazz.Constructors[i].Params;
 
2453
                                                        }
 
2454
                                                }
 
2455
                                        }
 
2456
                                        else if(clazz.Methods != null)
 
2457
                                        {
 
2458
                                                for(int i = 0; i < clazz.Methods.Length; i++)
 
2459
                                                {
 
2460
                                                        if(clazz.Methods[i].Name == method && clazz.Methods[i].Sig == sig)
 
2461
                                                        {
 
2462
                                                                return clazz.Methods[i].Params;
 
2463
                                                        }
 
2464
                                                }
 
2465
                                        }
 
2466
                                }
 
2467
                        }
 
2468
                        return null;
 
2469
                }
 
2470
 
 
2471
                internal bool IsGhost(TypeWrapper tw)
 
2472
                {
 
2473
                        return ghosts != null && tw.IsInterface && ghosts.ContainsKey(tw.Name);
 
2474
                }
 
2475
 
 
2476
                private void SetupGhosts(IKVM.Internal.MapXml.Root map)
 
2477
                {
 
2478
                        ghosts = new Dictionary<string, List<TypeWrapper>>();
 
2479
 
 
2480
                        // find the ghost interfaces
 
2481
                        foreach(IKVM.Internal.MapXml.Class c in map.assembly.Classes)
 
2482
                        {
 
2483
                                if(c.Shadows != null && c.Interfaces != null)
 
2484
                                {
 
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)
 
2489
                                        {
 
2490
                                                TypeWrapper ifaceWrapper = GetLoadedClass(iface.Name);
 
2491
                                                if(ifaceWrapper == null || !ifaceWrapper.TypeAsTBD.IsAssignableFrom(typeWrapper.TypeAsTBD))
 
2492
                                                {
 
2493
                                                        AddGhost(iface.Name, typeWrapper);
 
2494
                                                }
 
2495
                                        }
 
2496
                                }
 
2497
                        }
 
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);
 
2502
                }
 
2503
 
 
2504
                private void AddGhost(string interfaceName, TypeWrapper implementer)
 
2505
                {
 
2506
                        List<TypeWrapper> list;
 
2507
                        if(!ghosts.TryGetValue(interfaceName, out list))
 
2508
                        {
 
2509
                                list = new List<TypeWrapper>();
 
2510
                                ghosts[interfaceName] = list;
 
2511
                        }
 
2512
                        list.Add(implementer);
 
2513
                }
 
2514
 
 
2515
                internal TypeWrapper[] GetGhostImplementers(TypeWrapper wrapper)
 
2516
                {
 
2517
                        List<TypeWrapper> list;
 
2518
                        if (!ghosts.TryGetValue(wrapper.Name, out list))
 
2519
                        {
 
2520
                                return TypeWrapper.EmptyArray;
 
2521
                        }
 
2522
                        return list.ToArray();
 
2523
                }
 
2524
 
 
2525
                internal void FinishRemappedTypes()
 
2526
                {
 
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)
 
2531
                        {
 
2532
                                typeWrapper.Process3rdPass();
 
2533
                        }
 
2534
                        // 4th pass, implement methods/fields and bake the type
 
2535
                        foreach(RemapperTypeWrapper typeWrapper in remapped.Values)
 
2536
                        {
 
2537
                                typeWrapper.Process4thPass(remapped.Values);
 
2538
                        }
 
2539
 
 
2540
                        if(assemblyAttributes != null)
 
2541
                        {
 
2542
                                foreach(IKVM.Internal.MapXml.Attribute attr in assemblyAttributes)
 
2543
                                {
 
2544
                                        AttributeHelper.SetCustomAttribute(this, assemblyBuilder, attr);
 
2545
                                }
 
2546
                        }
 
2547
                }
 
2548
 
 
2549
                private static bool IsSigned(Assembly asm)
 
2550
                {
 
2551
                        byte[] key = asm.GetName().GetPublicKey();
 
2552
                        return key != null && key.Length != 0;
 
2553
                }
 
2554
 
 
2555
                internal static bool IsCoreAssembly(Assembly asm)
 
2556
                {
 
2557
                        return asm.IsDefined(StaticCompiler.GetRuntimeType("IKVM.Attributes.RemappedClassAttribute"), false);
 
2558
                }
 
2559
 
 
2560
                private bool CheckCompilingCoreAssembly()
 
2561
                {
 
2562
                        if (map != null && map.assembly != null && map.assembly.Classes != null)
 
2563
                        {
 
2564
                                foreach (IKVM.Internal.MapXml.Class c in map.assembly.Classes)
 
2565
                                {
 
2566
                                        if (c.Shadows != null && c.Name == "java.lang.Object")
 
2567
                                        {
 
2568
                                                return true;
 
2569
                                        }
 
2570
                                }
 
2571
                        }
 
2572
                        return false;
 
2573
                }
 
2574
 
 
2575
                internal static int Compile(string runtimeAssembly, List<CompilerOptions> optionsList)
 
2576
                {
 
2577
                        try
 
2578
                        {
 
2579
                                if(runtimeAssembly == null)
 
2580
                                {
 
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");
 
2583
                                }
 
2584
                                StaticCompiler.runtimeAssembly = StaticCompiler.LoadFile(runtimeAssembly);
 
2585
                                StaticCompiler.runtimeJniAssembly = StaticCompiler.LoadFile(Path.Combine(StaticCompiler.runtimeAssembly.Location, ".." + Path.DirectorySeparatorChar + "IKVM.Runtime.JNI.dll"));
 
2586
                        }
 
2587
                        catch(FileNotFoundException)
 
2588
                        {
 
2589
                                if(StaticCompiler.runtimeAssembly == null)
 
2590
                                {
 
2591
                                        throw new FatalCompilerErrorException(Message.RuntimeNotFound);
 
2592
                                }
 
2593
                                StaticCompiler.IssueMessage(Message.NoJniRuntime);
 
2594
                        }
 
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)
 
2599
                        {
 
2600
                                CompilerClassLoader compiler = null;
 
2601
                                int rc = CreateCompiler(options, ref compiler, ref compilingCoreAssembly);
 
2602
                                if(rc != 0)
 
2603
                                {
 
2604
                                        return rc;
 
2605
                                }
 
2606
                                compilers.Add(compiler);
 
2607
                                if(options.sharedclassloader != null)
 
2608
                                {
 
2609
                                        options.sharedclassloader.Add(compiler);
 
2610
                                }
 
2611
                        }
 
2612
                        foreach (CompilerClassLoader compiler1 in compilers)
 
2613
                        {
 
2614
                                foreach (CompilerClassLoader compiler2 in compilers)
 
2615
                                {
 
2616
                                        if (compiler1 != compiler2
 
2617
                                                && (compiler1.options.crossReferenceAllPeers || (compiler1.options.peerReferences != null && Array.IndexOf(compiler1.options.peerReferences, compiler2.options.assembly) != -1)))
 
2618
                                        {
 
2619
                                                compiler1.AddReference(compiler2);
 
2620
                                        }
 
2621
                                }
 
2622
                        }
 
2623
                        Dictionary<CompilerClassLoader, Type> mainAssemblyTypes = new Dictionary<CompilerClassLoader, Type>();
 
2624
                        foreach (CompilerClassLoader compiler in compilers)
 
2625
                        {
 
2626
                                if (compiler.options.sharedclassloader != null)
 
2627
                                {
 
2628
                                        Type mainAssemblyType;
 
2629
                                        if (!mainAssemblyTypes.TryGetValue(compiler.options.sharedclassloader[0], out mainAssemblyType))
 
2630
                                        {
 
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);
 
2635
                                        }
 
2636
                                        if (compiler.options.sharedclassloader[0] != compiler)
 
2637
                                        {
 
2638
                                                ((AssemblyBuilder)compiler.GetTypeWrapperFactory().ModuleBuilder.Assembly).__AddTypeForwarder(mainAssemblyType);
 
2639
                                        }
 
2640
                                }
 
2641
                                compiler.CompilePass1();
 
2642
                        }
 
2643
                        foreach (CompilerClassLoader compiler in compilers)
 
2644
                        {
 
2645
                                compiler.CompilePass2();
 
2646
                        }
 
2647
                        if (compilingCoreAssembly)
 
2648
                        {
 
2649
                                RuntimeHelperTypes.Create(compilers[0]);
 
2650
                        }
 
2651
                        foreach (CompilerClassLoader compiler in compilers)
 
2652
                        {
 
2653
                                compiler.EmitRemappedTypes2ndPass();
 
2654
                        }
 
2655
                        foreach (CompilerClassLoader compiler in compilers)
 
2656
                        {
 
2657
                                int rc = compiler.CompilePass3();
 
2658
                                if (rc != 0)
 
2659
                                {
 
2660
                                        return rc;
 
2661
                                }
 
2662
                        }
 
2663
                        Tracer.Info(Tracer.Compiler, "CompilerClassLoader.Save...");
 
2664
                        foreach (CompilerClassLoader compiler in compilers)
 
2665
                        {
 
2666
                                compiler.PrepareSave();
 
2667
                        }
 
2668
                        if (StaticCompiler.errorCount > 0)
 
2669
                        {
 
2670
                                return 1;
 
2671
                        }
 
2672
                        foreach (CompilerClassLoader compiler in compilers)
 
2673
                        {
 
2674
                                compiler.Save();
 
2675
                        }
 
2676
                        return StaticCompiler.errorCount == 0 ? 0 : 1;
 
2677
                }
 
2678
 
 
2679
                private static int CreateCompiler(CompilerOptions options, ref CompilerClassLoader loader, ref bool compilingCoreAssembly)
 
2680
                {
 
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])
 
2686
                        {
 
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())
 
2693
                                {
 
2694
                                        if(asmref.Name == runtimeAssemblyName.Name)
 
2695
                                        {
 
2696
                                                if(IsSigned(StaticCompiler.runtimeAssembly))
 
2697
                                                {
 
2698
                                                        // TODO we really should support binding redirects here to allow different revisions to be mixed
 
2699
                                                        if(asmref.FullName != runtimeAssemblyName.FullName)
 
2700
                                                        {
 
2701
                                                                throw new FatalCompilerErrorException(Message.RuntimeMismatch, reference.Location, runtimeAssemblyName.FullName, asmref.FullName);
 
2702
                                                        }
 
2703
                                                }
 
2704
                                                else
 
2705
                                                {
 
2706
                                                        if(asmref.GetPublicKeyToken() != null && asmref.GetPublicKeyToken().Length != 0)
 
2707
                                                        {
 
2708
                                                                throw new FatalCompilerErrorException(Message.RuntimeMismatch, reference.Location, runtimeAssemblyName.FullName, asmref.FullName);
 
2709
                                                        }
 
2710
                                                }
 
2711
                                        }
 
2712
                                }
 
2713
                        }
 
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)
 
2718
                        {
 
2719
                                ClassFile f;
 
2720
                                try
 
2721
                                {
 
2722
                                        byte[] buf = kv.Value.data;
 
2723
                                        f = new ClassFile(buf, 0, buf.Length, null, ClassFileParseOptions.None);
 
2724
                                        if(!f.IsInterface && f.SuperClass != null)
 
2725
                                        {
 
2726
                                                baseClasses[f.SuperClass] = f.SuperClass;
 
2727
                                        }
 
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)
 
2731
                                        {
 
2732
                                                assemblyAnnotations.AddRange(f.Annotations);
 
2733
                                        }
 
2734
                                }
 
2735
                                catch(ClassFormatError)
 
2736
                                {
 
2737
                                        continue;
 
2738
                                }
 
2739
                                if(options.mainClass == null && (options.guessFileKind || options.target != PEFileKinds.Dll))
 
2740
                                {
 
2741
                                        foreach(ClassFile.Method m in f.Methods)
 
2742
                                        {
 
2743
                                                if(m.IsPublic && m.IsStatic && m.Name == "main" && m.Signature == "([Ljava.lang.String;)V")
 
2744
                                                {
 
2745
                                                        StaticCompiler.IssueMessage(Message.MainMethodFound, f.Name);
 
2746
                                                        options.mainClass = f.Name;
 
2747
                                                        break;
 
2748
                                                }
 
2749
                                        }
 
2750
                                }
 
2751
                        }
 
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)
 
2756
                        {
 
2757
                                string name = kv.Key;
 
2758
                                bool excluded = false;
 
2759
                                for(int j = 0; j < options.classesToExclude.Length; j++)
 
2760
                                {
 
2761
                                        if(Regex.IsMatch(name, options.classesToExclude[j]))
 
2762
                                        {
 
2763
                                                excluded = true;
 
2764
                                                break;
 
2765
                                        }
 
2766
                                }
 
2767
                                if(h.ContainsKey(name))
 
2768
                                {
 
2769
                                        StaticCompiler.IssueMessage(Message.DuplicateClassName, name);
 
2770
                                        excluded = true;
 
2771
                                }
 
2772
                                if(!excluded)
 
2773
                                {
 
2774
                                        h[name] = kv.Value;
 
2775
                                }
 
2776
                        }
 
2777
                        options.classes = null;
 
2778
 
 
2779
                        if(options.guessFileKind && options.mainClass == null)
 
2780
                        {
 
2781
                                options.target = PEFileKinds.Dll;
 
2782
                        }
 
2783
 
 
2784
                        if(options.target == PEFileKinds.Dll && options.mainClass != null)
 
2785
                        {
 
2786
                                throw new FatalCompilerErrorException(Message.MainClassRequiresExe);
 
2787
                        }
 
2788
 
 
2789
                        if(options.target != PEFileKinds.Dll && options.mainClass == null)
 
2790
                        {
 
2791
                                throw new FatalCompilerErrorException(Message.ExeRequiresMainClass);
 
2792
                        }
 
2793
 
 
2794
                        if(options.target == PEFileKinds.Dll && options.props.Count != 0)
 
2795
                        {
 
2796
                                throw new FatalCompilerErrorException(Message.PropertiesRequireExe);
 
2797
                        }
 
2798
 
 
2799
                        if(options.path == null)
 
2800
                        {
 
2801
                                if(options.target == PEFileKinds.Dll)
 
2802
                                {
 
2803
                                        if(options.targetIsModule)
 
2804
                                        {
 
2805
                                                options.path = options.assembly + ".netmodule";
 
2806
                                        }
 
2807
                                        else
 
2808
                                        {
 
2809
                                                options.path = options.assembly + ".dll";
 
2810
                                        }
 
2811
                                }
 
2812
                                else
 
2813
                                {
 
2814
                                        options.path = options.assembly + ".exe";
 
2815
                                }
 
2816
                                StaticCompiler.IssueMessage(Message.OutputFileIs, options.path);
 
2817
                        }
 
2818
 
 
2819
                        if(options.targetIsModule)
 
2820
                        {
 
2821
                                if(options.classLoader != null)
 
2822
                                {
 
2823
                                        throw new FatalCompilerErrorException(Message.ModuleCannotHaveClassLoader);
 
2824
                                }
 
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;
 
2827
                        }
 
2828
 
 
2829
                        Tracer.Info(Tracer.Compiler, "Constructing compiler");
 
2830
                        AssemblyClassLoader[] referencedAssemblies = new AssemblyClassLoader[references.Count];
 
2831
                        for(int i = 0; i < references.Count; i++)
 
2832
                        {
 
2833
                                AssemblyClassLoader acl = AssemblyClassLoader.FromAssembly(references[i]);
 
2834
                                if (acl.MainAssembly != references[i])
 
2835
                                {
 
2836
                                        StaticCompiler.IssueMessage(options, Message.NonPrimaryAssemblyReference, references[i].GetName().Name, acl.MainAssembly.GetName().Name);
 
2837
                                }
 
2838
                                if (Array.IndexOf(referencedAssemblies, acl) != -1)
 
2839
                                {
 
2840
                                        StaticCompiler.IssueMessage(options, Message.DuplicateAssemblyReference, acl.MainAssembly.FullName);
 
2841
                                }
 
2842
                                referencedAssemblies[i] = acl;
 
2843
                        }
 
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)
 
2849
                        {
 
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);
 
2854
                                FileStream fs;
 
2855
                                try
 
2856
                                {
 
2857
                                        fs = File.OpenRead(options.remapfile);
 
2858
                                }
 
2859
                                catch(Exception x)
 
2860
                                {
 
2861
                                        throw new FatalCompilerErrorException(Message.ErrorReadingFile, options.remapfile, x.Message);
 
2862
                                }
 
2863
                                try
 
2864
                                {
 
2865
                                        XmlTextReader rdr = new XmlTextReader(fs);
 
2866
                                        IKVM.Internal.MapXml.Root.xmlReader = rdr;
 
2867
                                        IKVM.Internal.MapXml.Root map;
 
2868
                                        try
 
2869
                                        {
 
2870
                                                map = (IKVM.Internal.MapXml.Root)ser.Deserialize(rdr);
 
2871
                                        }
 
2872
                                        catch(InvalidOperationException x)
 
2873
                                        {
 
2874
                                                throw new FatalCompilerErrorException(Message.ErrorParsingMapFile, options.remapfile, x.Message);
 
2875
                                        }
 
2876
                                        if(!loader.ValidateAndSetMap(map))
 
2877
                                        {
 
2878
                                                return 1;
 
2879
                                        }
 
2880
                                }
 
2881
                                finally
 
2882
                                {
 
2883
                                        fs.Close();
 
2884
                                }
 
2885
                                if(loader.CheckCompilingCoreAssembly())
 
2886
                                {
 
2887
                                        compilingCoreAssembly = true;
 
2888
                                        ClassLoaderWrapper.SetBootstrapClassLoader(loader);
 
2889
                                }
 
2890
                        }
 
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)
 
2894
                        {
 
2895
                                foreach(AssemblyName name in StaticCompiler.runtimeAssembly.GetReferencedAssemblies())
 
2896
                                {
 
2897
                                        Assembly asm = null;
 
2898
                                        try
 
2899
                                        {
 
2900
                                                asm = LoadReferencedAssembly(StaticCompiler.runtimeAssembly.Location + "/../" + name.Name + ".dll");
 
2901
                                        }
 
2902
                                        catch(FileNotFoundException)
 
2903
                                        {
 
2904
                                        }
 
2905
                                        if(asm != null && IsCoreAssembly(asm))
 
2906
                                        {
 
2907
                                                JVM.CoreAssembly = asm;
 
2908
                                                break;
 
2909
                                        }
 
2910
                                }
 
2911
                                if(JVM.CoreAssembly == null)
 
2912
                                {
 
2913
                                        throw new FatalCompilerErrorException(Message.BootstrapClassesMissing);
 
2914
                                }
 
2915
                                // we need to scan again for remapped types, now that we've loaded the core library
 
2916
                                ClassLoaderWrapper.LoadRemappedTypes();
 
2917
                        }
 
2918
 
 
2919
                        if(!compilingCoreAssembly)
 
2920
                        {
 
2921
                                allReferencesAreStrongNamed &= IsSigned(JVM.CoreAssembly);
 
2922
                                loader.AddReference(AssemblyClassLoader.FromAssembly(JVM.CoreAssembly));
 
2923
                        }
 
2924
 
 
2925
                        if((options.keyPair != null || options.publicKey != null) && !allReferencesAreStrongNamed)
 
2926
                        {
 
2927
                                throw new FatalCompilerErrorException(Message.StrongNameRequiresStrongNamedRefs);
 
2928
                        }
 
2929
 
 
2930
                        if(loader.map != null)
 
2931
                        {
 
2932
                                loader.LoadMapXml();
 
2933
                        }
 
2934
 
 
2935
                        if(!compilingCoreAssembly)
 
2936
                        {
 
2937
                                FakeTypes.Load(JVM.CoreAssembly);
 
2938
                        }
 
2939
                        return 0;
 
2940
                }
 
2941
 
 
2942
                private static Assembly LoadReferencedAssembly(string r)
 
2943
                {
 
2944
                        Assembly asm = StaticCompiler.LoadFile(r);
 
2945
                        return asm;
 
2946
                }
 
2947
 
 
2948
                private bool IsStub(string className)
 
2949
                {
 
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
 
2952
                        ClassItem classdef;
 
2953
                        if (classes.TryGetValue(className, out classdef))
 
2954
                        {
 
2955
                                try
 
2956
                                {
 
2957
                                        return new ClassFile(classdef.data, 0, classdef.data.Length, className, ClassFileParseOptions.RelaxedClassNameValidation).IKVMAssemblyAttribute != null;
 
2958
                                }
 
2959
                                catch (ClassFormatError)
 
2960
                                {
 
2961
                                }
 
2962
                        }
 
2963
                        return false;
 
2964
                }
 
2965
 
 
2966
                private void CompilePass1()
 
2967
                {
 
2968
                        Tracer.Info(Tracer.Compiler, "Compiling class files (1)");
 
2969
                        if(CheckCompilingCoreAssembly())
 
2970
                        {
 
2971
                                EmitRemappedTypes();
 
2972
                        }
 
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())
 
2977
                        {
 
2978
                                FakeTypes.Create(GetTypeWrapperFactory().ModuleBuilder, this);
 
2979
                        }
 
2980
                        if(options.sharedclassloader != null && options.sharedclassloader[0] != this)
 
2981
                        {
 
2982
                                packages = options.sharedclassloader[0].packages;
 
2983
                        }
 
2984
                        else
 
2985
                        {
 
2986
                                packages = new Dictionary<string, string>();
 
2987
                        }
 
2988
                        allwrappers = new List<TypeWrapper>();
 
2989
                        foreach(string s in classesToCompile)
 
2990
                        {
 
2991
                                TypeWrapper wrapper = LoadClassByDottedNameFast(s);
 
2992
                                if(wrapper != null)
 
2993
                                {
 
2994
                                        ClassLoaderWrapper loader = wrapper.GetClassLoader();
 
2995
                                        if(loader != this)
 
2996
                                        {
 
2997
                                                if(!(loader is GenericClassLoader || loader is CompilerClassLoader || (importedStubTypes.ContainsKey(s) && importedStubTypes[s] == wrapper) || IsStub(s)))
 
2998
                                                {
 
2999
                                                        StaticCompiler.IssueMessage(options, Message.SkippingReferencedClass, s, ((AssemblyClassLoader)loader).GetAssembly(wrapper).FullName);
 
3000
                                                }
 
3001
                                                continue;
 
3002
                                        }
 
3003
                                        int pos = wrapper.Name.LastIndexOf('.');
 
3004
                                        if(pos != -1)
 
3005
                                        {
 
3006
                                                packages[wrapper.Name.Substring(0, pos)] = "";
 
3007
                                        }
 
3008
                                        if(options.sharedclassloader != null && options.sharedclassloader[0] != this)
 
3009
                                        {
 
3010
                                                options.sharedclassloader[0].dynamicallyImportedTypes.Add(wrapper);
 
3011
                                        }
 
3012
                                        allwrappers.Add(wrapper);
 
3013
                                }
 
3014
                        }
 
3015
                }
 
3016
 
 
3017
                private void CompilePass2()
 
3018
                {
 
3019
                        Tracer.Info(Tracer.Compiler, "Compiling class files (2)");
 
3020
                        foreach(TypeWrapper tw in allwrappers)
 
3021
                        {
 
3022
                                DynamicTypeWrapper dtw = tw as DynamicTypeWrapper;
 
3023
                                if(dtw != null)
 
3024
                                {
 
3025
                                        dtw.CreateStep2();
 
3026
                                }
 
3027
                        }
 
3028
                }
 
3029
 
 
3030
                private int CompilePass3()
 
3031
                {
 
3032
                        Tracer.Info(Tracer.Compiler, "Compiling class files (3)");
 
3033
                        if(map != null && CheckCompilingCoreAssembly())
 
3034
                        {
 
3035
                                FakeTypes.Finish(this);
 
3036
                        }
 
3037
                        foreach(string proxy in options.proxies)
 
3038
                        {
 
3039
                                ProxyGenerator.Create(this, proxy);
 
3040
                        }
 
3041
                        if(options.mainClass != null)
 
3042
                        {
 
3043
                                TypeWrapper wrapper = null;
 
3044
                                try
 
3045
                                {
 
3046
                                        wrapper = LoadClassByDottedNameFast(options.mainClass);
 
3047
                                }
 
3048
                                catch(RetargetableJavaException)
 
3049
                                {
 
3050
                                }
 
3051
                                if(wrapper == null)
 
3052
                                {
 
3053
                                        throw new FatalCompilerErrorException(Message.MainClassNotFound);
 
3054
                                }
 
3055
                                MethodWrapper mw = wrapper.GetMethodWrapper("main", "([Ljava.lang.String;)V", false);
 
3056
                                if(mw == null || !mw.IsStatic)
 
3057
                                {
 
3058
                                        throw new FatalCompilerErrorException(Message.MainMethodNotFound);
 
3059
                                }
 
3060
                                mw.Link();
 
3061
                                MethodInfo method = mw.GetMethod() as MethodInfo;
 
3062
                                if(method == null)
 
3063
                                {
 
3064
                                        throw new FatalCompilerErrorException(Message.UnsupportedMainMethod);
 
3065
                                }
 
3066
                                if(!ReflectUtil.IsFromAssembly(method.DeclaringType, assemblyBuilder)
 
3067
                                        && (!method.IsPublic || !method.DeclaringType.IsPublic))
 
3068
                                {
 
3069
                                        throw new FatalCompilerErrorException(Message.ExternalMainNotAccessible);
 
3070
                                }
 
3071
                                Type apartmentAttributeType = null;
 
3072
                                if(options.apartment == ApartmentState.STA)
 
3073
                                {
 
3074
                                        apartmentAttributeType = JVM.Import(typeof(STAThreadAttribute));
 
3075
                                }
 
3076
                                else if(options.apartment == ApartmentState.MTA)
 
3077
                                {
 
3078
                                        apartmentAttributeType = JVM.Import(typeof(MTAThreadAttribute));
 
3079
                                }
 
3080
                                SetMain(method, options.target, options.props, options.noglobbing, apartmentAttributeType);
 
3081
                        }
 
3082
                        if(map != null)
 
3083
                        {
 
3084
                                LoadMappedExceptions(map);
 
3085
                                Tracer.Info(Tracer.Compiler, "Loading remapped types (2)");
 
3086
                                FinishRemappedTypes();
 
3087
                        }
 
3088
                        Tracer.Info(Tracer.Compiler, "Compiling class files (2)");
 
3089
                        AddResources(options.resources, options.compressedResources);
 
3090
                        if(options.externalResources != null)
 
3091
                        {
 
3092
                                foreach(KeyValuePair<string, string> kv in options.externalResources)
 
3093
                                {
 
3094
                                        assemblyBuilder.AddResourceFile(JVM.MangleResourceName(kv.Key), kv.Value);
 
3095
                                }
 
3096
                        }
 
3097
                        if(options.fileversion != null)
 
3098
                        {
 
3099
                                CustomAttributeBuilder filever = new CustomAttributeBuilder(JVM.Import(typeof(System.Reflection.AssemblyFileVersionAttribute)).GetConstructor(new Type[] { Types.String }), new object[] { options.fileversion });
 
3100
                                assemblyBuilder.SetCustomAttribute(filever);
 
3101
                        }
 
3102
                        foreach(object[] def in assemblyAnnotations)
 
3103
                        {
 
3104
                                Annotation annotation = Annotation.Load(this, def);
 
3105
                                if(annotation != null)
 
3106
                                {
 
3107
                                        annotation.Apply(this, assemblyBuilder, def);
 
3108
                                }
 
3109
                        }
 
3110
                        if(options.classLoader != null)
 
3111
                        {
 
3112
                                TypeWrapper wrapper = null;
 
3113
                                try
 
3114
                                {
 
3115
                                        wrapper = LoadClassByDottedNameFast(options.classLoader);
 
3116
                                }
 
3117
                                catch(RetargetableJavaException)
 
3118
                                {
 
3119
                                }
 
3120
                                if(wrapper == null)
 
3121
                                {
 
3122
                                        throw new FatalCompilerErrorException(Message.ClassLoaderNotFound);
 
3123
                                }
 
3124
                                if(!wrapper.IsPublic && !ReflectUtil.IsFromAssembly(wrapper.TypeAsBaseType, assemblyBuilder))
 
3125
                                {
 
3126
                                        throw new FatalCompilerErrorException(Message.ClassLoaderNotAccessible);
 
3127
                                }
 
3128
                                if(wrapper.IsAbstract)
 
3129
                                {
 
3130
                                        throw new FatalCompilerErrorException(Message.ClassLoaderIsAbstract);
 
3131
                                }
 
3132
                                if(!wrapper.IsAssignableTo(ClassLoaderWrapper.LoadClassCritical("java.lang.ClassLoader")))
 
3133
                                {
 
3134
                                        throw new FatalCompilerErrorException(Message.ClassLoaderNotClassLoader);
 
3135
                                }
 
3136
                                MethodWrapper mw = wrapper.GetMethodWrapper("<init>", "(Lcli.System.Reflection.Assembly;)V", false);
 
3137
                                if(mw == null)
 
3138
                                {
 
3139
                                        throw new FatalCompilerErrorException(Message.ClassLoaderConstructorMissing);
 
3140
                                }
 
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)
 
3147
                                {
 
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);
 
3155
                                }
 
3156
                        }
 
3157
                        if (options.iconfile != null)
 
3158
                        {
 
3159
                                assemblyBuilder.__DefineIconResource(IkvmcCompiler.ReadAllBytes(options.iconfile));
 
3160
                        }
 
3161
                        if (options.manifestFile != null)
 
3162
                        {
 
3163
                                assemblyBuilder.__DefineManifestResource(IkvmcCompiler.ReadAllBytes(options.manifestFile));
 
3164
                        }
 
3165
                        assemblyBuilder.DefineVersionInfoResource();
 
3166
                        return 0;
 
3167
                }
 
3168
 
 
3169
                private static void ser_UnknownElement(object sender, System.Xml.Serialization.XmlElementEventArgs e)
 
3170
                {
 
3171
                        StaticCompiler.IssueMessage(Message.UnknownElementInMapFile, e.Element.Name, e.LineNumber.ToString(), e.LinePosition.ToString());
 
3172
                }
 
3173
 
 
3174
                private static void ser_UnknownAttribute(object sender, System.Xml.Serialization.XmlAttributeEventArgs e)
 
3175
                {
 
3176
                        StaticCompiler.IssueMessage(Message.UnknownAttributeInMapFile, e.Attr.Name, e.LineNumber.ToString(), e.LinePosition.ToString());
 
3177
                }
 
3178
 
 
3179
                private bool ValidateAndSetMap(IKVM.Internal.MapXml.Root map)
 
3180
                {
 
3181
                        bool valid = true;
 
3182
                        if (map.assembly != null)
 
3183
                        {
 
3184
                                if (map.assembly.Classes != null)
 
3185
                                {
 
3186
                                        foreach (IKVM.Internal.MapXml.Class c in map.assembly.Classes)
 
3187
                                        {
 
3188
                                                if (c.Fields != null)
 
3189
                                                {
 
3190
                                                        foreach (IKVM.Internal.MapXml.Field f in c.Fields)
 
3191
                                                        {
 
3192
                                                                ValidateNameSig("field", c.Name, f.Name, f.Sig, ref valid, true);
 
3193
                                                        }
 
3194
                                                }
 
3195
                                                if (c.Methods != null)
 
3196
                                                {
 
3197
                                                        foreach (IKVM.Internal.MapXml.Method m in c.Methods)
 
3198
                                                        {
 
3199
                                                                ValidateNameSig("method", c.Name, m.Name, m.Sig, ref valid, false);
 
3200
                                                        }
 
3201
                                                }
 
3202
                                                if (c.Constructors != null)
 
3203
                                                {
 
3204
                                                        foreach (IKVM.Internal.MapXml.Constructor ctor in c.Constructors)
 
3205
                                                        {
 
3206
                                                                ValidateNameSig("constructor", c.Name, "<init>", ctor.Sig, ref valid, false);
 
3207
                                                        }
 
3208
                                                }
 
3209
                                                if (c.Properties != null)
 
3210
                                                {
 
3211
                                                        foreach (IKVM.Internal.MapXml.Property prop in c.Properties)
 
3212
                                                        {
 
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);
 
3216
                                                        }
 
3217
                                                }
 
3218
                                        }
 
3219
                                }
 
3220
                        }
 
3221
                        this.map = map;
 
3222
                        return valid;
 
3223
                }
 
3224
 
 
3225
                private static void ValidateNameSig(string member, string clazz, string name, string sig, ref bool valid, bool field)
 
3226
                {
 
3227
                        if (!IsValidName(name))
 
3228
                        {
 
3229
                                valid = false;
 
3230
                                StaticCompiler.IssueMessage(Message.InvalidMemberNameInMapFile, member, name, clazz);
 
3231
                        }
 
3232
                        if (!IsValidSig(sig, field))
 
3233
                        {
 
3234
                                valid = false;
 
3235
                                StaticCompiler.IssueMessage(Message.InvalidMemberSignatureInMapFile, member, clazz, name, sig);
 
3236
                        }
 
3237
                }
 
3238
 
 
3239
                private static void ValidatePropertyGetterSetter(string getterOrSetter, string clazz, string property, IKVM.Internal.MapXml.Method method, ref bool valid)
 
3240
                {
 
3241
                        if (method != null)
 
3242
                        {
 
3243
                                if (!IsValidName(method.Name))
 
3244
                                {
 
3245
                                        valid = false;
 
3246
                                        StaticCompiler.IssueMessage(Message.InvalidPropertyNameInMapFile, getterOrSetter, clazz, property, method.Name);
 
3247
                                }
 
3248
                                if (!ClassFile.IsValidMethodSig(method.Sig))
 
3249
                                {
 
3250
                                        valid = false;
 
3251
                                        StaticCompiler.IssueMessage(Message.InvalidPropertySignatureInMapFile, getterOrSetter, clazz, property, method.Sig);
 
3252
                                }
 
3253
                        }
 
3254
                }
 
3255
 
 
3256
                private static bool IsValidName(string name)
 
3257
                {
 
3258
                        return name != null && name.Length != 0;
 
3259
                }
 
3260
 
 
3261
                private static bool IsValidSig(string sig, bool field)
 
3262
                {
 
3263
                        return sig != null && (field ? ClassFile.IsValidFieldSig(sig) : ClassFile.IsValidMethodSig(sig));
 
3264
                }
 
3265
 
 
3266
                internal Type GetTypeFromReferencedAssembly(string name)
 
3267
                {
 
3268
                        foreach (AssemblyClassLoader acl in referencedAssemblies)
 
3269
                        {
 
3270
                                Type type = acl.MainAssembly.GetType(name, false);
 
3271
                                if (type != null)
 
3272
                                {
 
3273
                                        return type;
 
3274
                                }
 
3275
                        }
 
3276
                        return null;
 
3277
                }
 
3278
 
 
3279
                internal override void IssueMessage(Message msgId, params string[] values)
 
3280
                {
 
3281
                        StaticCompiler.IssueMessage(options, msgId, values);
 
3282
                }
 
3283
 
 
3284
                internal bool TryEnableUnmanagedExports()
 
3285
                {
 
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)
 
3290
                        {
 
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;
 
3293
                                return true;
 
3294
                        }
 
3295
                        else
 
3296
                        {
 
3297
                                StaticCompiler.IssueMessage(options, Message.DllExportRequiresSupportedPlatform);
 
3298
                                return false;
 
3299
                        }
 
3300
                }
 
3301
        }
 
3302
 
 
3303
        struct ClassItem
 
3304
        {
 
3305
                internal byte[] data;
 
3306
                internal string path;
 
3307
        }
 
3308
 
 
3309
        struct ResourceItem
 
3310
        {
 
3311
                internal ICSharpCode.SharpZipLib.Zip.ZipEntry zipEntry;
 
3312
                internal byte[] data;
 
3313
                internal string jar;
 
3314
        }
 
3315
 
 
3316
        sealed class CompilerOptions
 
3317
        {
 
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>();
 
3363
 
 
3364
                internal CompilerOptions Copy()
 
3365
                {
 
3366
                        CompilerOptions copy = (CompilerOptions)MemberwiseClone();
 
3367
                        if (classes != null)
 
3368
                        {
 
3369
                                copy.classes = new Dictionary<string, ClassItem>(classes);
 
3370
                        }
 
3371
                        if (resources != null)
 
3372
                        {
 
3373
                                copy.resources = Copy(resources);
 
3374
                        }
 
3375
                        if (props != null)
 
3376
                        {
 
3377
                                copy.props = new Dictionary<string, string>(props);
 
3378
                        }
 
3379
                        if (externalResources != null)
 
3380
                        {
 
3381
                                copy.externalResources = new Dictionary<string, string>(externalResources);
 
3382
                        }
 
3383
                        copy.suppressWarnings = new Dictionary<string, string>(suppressWarnings);
 
3384
                        copy.errorWarnings = new Dictionary<string, string>(errorWarnings);
 
3385
                        return copy;
 
3386
                }
 
3387
 
 
3388
                internal static Dictionary<string, List<ResourceItem>> Copy(Dictionary<string, List<ResourceItem>> resources)
 
3389
                {
 
3390
                        Dictionary<string, List<ResourceItem>> copy = new Dictionary<string, List<ResourceItem>>();
 
3391
                        foreach (KeyValuePair<string, List<ResourceItem>> kv in resources)
 
3392
                        {
 
3393
                                copy.Add(kv.Key, new List<ResourceItem>(kv.Value));
 
3394
                        }
 
3395
                        return copy;
 
3396
                }
 
3397
        }
 
3398
 
 
3399
        enum Message
 
3400
        {
 
3401
                // These are the informational messages
 
3402
                MainMethodFound = 1,
 
3403
                OutputFileIs = 2,
 
3404
                AutoAddRef = 3,
 
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,
 
3418
                NoJniRuntime= 110,
 
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
 
3443
                StartErrors = 4000,
 
3444
                UnableToCreateProxy = 4001,
 
3445
                DuplicateProxy = 4002,
 
3446
                MapXmlUnableToResolveOpCode = 4003,
 
3447
                MapXmlError = 4004,
 
3448
                InputFileNotFound = 4005,
 
3449
                UnknownFileType = 4006,
 
3450
                UnknownElementInMapFile = 4007,
 
3451
                UnknownAttributeInMapFile = 4008,
 
3452
                InvalidMemberNameInMapFile = 4009,
 
3453
                InvalidMemberSignatureInMapFile = 4010,
 
3454
                InvalidPropertyNameInMapFile = 4011,
 
3455
                InvalidPropertySignatureInMapFile = 4012,
 
3456
                // Fatal errors
 
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,
 
3470
                PathTooLong = 5013,
 
3471
                PathNotFound = 5014,
 
3472
                InvalidPath = 5015,
 
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,
 
3510
        }
 
3511
 
 
3512
        static class StaticCompiler
 
3513
        {
 
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;
 
3519
 
 
3520
                internal static Assembly Load(string assemblyString)
 
3521
                {
 
3522
                        return Universe.Load(assemblyString);
 
3523
                }
 
3524
 
 
3525
                internal static Assembly LoadFile(string path)
 
3526
                {
 
3527
                        return Universe.LoadFile(path);
 
3528
                }
 
3529
 
 
3530
                internal static Type GetRuntimeType(string name)
 
3531
                {
 
3532
                        Type type = runtimeAssembly.GetType(name);
 
3533
                        if (type != null)
 
3534
                        {
 
3535
                                return type;
 
3536
                        }
 
3537
                        if (runtimeJniAssembly != null)
 
3538
                        {
 
3539
                                return runtimeJniAssembly.GetType(name, true);
 
3540
                        }
 
3541
                        else
 
3542
                        {
 
3543
                                throw new TypeLoadException(name);
 
3544
                        }
 
3545
                }
 
3546
 
 
3547
                internal static Type GetTypeForMapXml(ClassLoaderWrapper loader, string name)
 
3548
                {
 
3549
                        Type type = GetType(loader, name);
 
3550
                        if (type == null)
 
3551
                        {
 
3552
                                throw new FatalCompilerErrorException(Message.MapFileTypeNotFound, name);
 
3553
                        }
 
3554
                        return type;
 
3555
                }
 
3556
 
 
3557
                internal static TypeWrapper GetClassForMapXml(ClassLoaderWrapper loader, string name)
 
3558
                {
 
3559
                        TypeWrapper tw = loader.LoadClassByDottedNameFast(name);
 
3560
                        if (tw == null)
 
3561
                        {
 
3562
                                throw new FatalCompilerErrorException(Message.MapFileClassNotFound, name);
 
3563
                        }
 
3564
                        return tw;
 
3565
                }
 
3566
 
 
3567
                internal static Type GetType(ClassLoaderWrapper loader, string name)
 
3568
                {
 
3569
                        CompilerClassLoader ccl = (CompilerClassLoader)loader;
 
3570
                        return ccl.GetTypeFromReferencedAssembly(name);
 
3571
                }
 
3572
 
 
3573
                internal static void IssueMessage(Message msgId, params string[] values)
 
3574
                {
 
3575
                        IssueMessage(toplevel, msgId, values);
 
3576
                }
 
3577
 
 
3578
                internal static void IssueMessage(CompilerOptions options, Message msgId, params string[] values)
 
3579
                {
 
3580
                        StringBuilder sb = new StringBuilder();
 
3581
                        sb.Append((int)msgId);
 
3582
                        if(values.Length > 0)
 
3583
                        {
 
3584
                                sb.Append(':').Append(values[0]);
 
3585
                        }
 
3586
                        string key = sb.ToString();
 
3587
                        if(options.suppressWarnings.ContainsKey(key)
 
3588
                                || options.suppressWarnings.ContainsKey(((int)msgId).ToString()))
 
3589
                        {
 
3590
                                return;
 
3591
                        }
 
3592
                        options.suppressWarnings.Add(key, key);
 
3593
                        if(options.writeSuppressWarningsFile != null)
 
3594
                        {
 
3595
                                File.AppendAllText(options.writeSuppressWarningsFile, "-nowarn:" + key + Environment.NewLine);
 
3596
                        }
 
3597
                        string msg;
 
3598
                        switch(msgId)
 
3599
                        {
 
3600
                                case Message.MainMethodFound:
 
3601
                                        msg = "Found main method in class \"{0}\"";
 
3602
                                        break;
 
3603
                                case Message.OutputFileIs:
 
3604
                                        msg = "Output file is \"{0}\"";
 
3605
                                        break;
 
3606
                                case Message.AutoAddRef:
 
3607
                                        msg = "Automatically adding reference to \"{0}\"";
 
3608
                                        break;
 
3609
                                case Message.MainMethodFromManifest:
 
3610
                                        msg = "Using main class \"{0}\" based on jar manifest";
 
3611
                                        break;
 
3612
                                case Message.ClassNotFound:
 
3613
                                        msg = "Class \"{0}\" not found";
 
3614
                                        break;
 
3615
                                case Message.ClassFormatError:
 
3616
                                        msg = "Unable to compile class \"{0}\"" + Environment.NewLine + 
 
3617
                                                "    (class format error \"{1}\")";
 
3618
                                        break;
 
3619
                                case Message.DuplicateClassName:
 
3620
                                        msg = "Duplicate class name: \"{0}\"";
 
3621
                                        break;
 
3622
                                case Message.IllegalAccessError:
 
3623
                                        msg = "Unable to compile class \"{0}\"" + Environment.NewLine + 
 
3624
                                                "    (illegal access error \"{1}\")";
 
3625
                                        break;
 
3626
                                case Message.VerificationError:
 
3627
                                        msg = "Unable to compile class \"{0}\"" + Environment.NewLine + 
 
3628
                                                "    (verification error \"{1}\")";
 
3629
                                        break;
 
3630
                                case Message.NoClassDefFoundError:
 
3631
                                        msg = "Unable to compile class \"{0}\"" + Environment.NewLine + 
 
3632
                                                "    (missing class \"{1}\")";
 
3633
                                        break;
 
3634
                                case Message.GenericUnableToCompileError:
 
3635
                                        msg = "Unable to compile class \"{0}\"" + Environment.NewLine + 
 
3636
                                                "    (\"{1}\": \"{2}\")";
 
3637
                                        break;
 
3638
                                case Message.DuplicateResourceName:
 
3639
                                        msg = "Skipping resource (name clash): \"{0}\"";
 
3640
                                        break;
 
3641
                                case Message.NotAClassFile:
 
3642
                                        msg = "Not a class file \"{0}\", including it as resource" + Environment.NewLine +
 
3643
                                                "    (class format error \"{1}\")";
 
3644
                                        break;
 
3645
                                case Message.SkippingReferencedClass:
 
3646
                                        msg = "Skipping class: \"{0}\"" + Environment.NewLine +
 
3647
                                                "    (class is already available in referenced assembly \"{1}\")";
 
3648
                                        break;
 
3649
                                case Message.NoJniRuntime:
 
3650
                                        msg = "Unable to load runtime JNI assembly";
 
3651
                                        break;
 
3652
                                case Message.EmittedNoClassDefFoundError:
 
3653
                                        msg = "Emitted java.lang.NoClassDefFoundError in \"{0}\"" + Environment.NewLine +
 
3654
                                                "    (\"{1}\")";
 
3655
                                        break;
 
3656
                                case Message.EmittedIllegalAccessError:
 
3657
                                        msg = "Emitted java.lang.IllegalAccessError in \"{0}\"" + Environment.NewLine +
 
3658
                                                "    (\"{1}\")";
 
3659
                                        break;
 
3660
                                case Message.EmittedInstantiationError:
 
3661
                                        msg = "Emitted java.lang.InstantiationError in \"{0}\"" + Environment.NewLine +
 
3662
                                                "    (\"{1}\")";
 
3663
                                        break;
 
3664
                                case Message.EmittedIncompatibleClassChangeError:
 
3665
                                        msg = "Emitted java.lang.IncompatibleClassChangeError in \"{0}\"" + Environment.NewLine +
 
3666
                                                "    (\"{1}\")";
 
3667
                                        break;
 
3668
                                case Message.EmittedNoSuchFieldError:
 
3669
                                        msg = "Emitted java.lang.NoSuchFieldError in \"{0}\"" + Environment.NewLine +
 
3670
                                                "    (\"{1}\")";
 
3671
                                        break;
 
3672
                                case Message.EmittedAbstractMethodError:
 
3673
                                        msg = "Emitted java.lang.AbstractMethodError in \"{0}\"" + Environment.NewLine +
 
3674
                                                "    (\"{1}\")";
 
3675
                                        break;
 
3676
                                case Message.EmittedNoSuchMethodError:
 
3677
                                        msg = "Emitted java.lang.NoSuchMethodError in \"{0}\"" + Environment.NewLine +
 
3678
                                                "    (\"{1}\")";
 
3679
                                        break;
 
3680
                                case Message.EmittedLinkageError:
 
3681
                                        msg = "Emitted java.lang.LinkageError in \"{0}\"" + Environment.NewLine +
 
3682
                                                "    (\"{1}\")";
 
3683
                                        break;
 
3684
                                case Message.EmittedVerificationError:
 
3685
                                        msg = "Emitted java.lang.VerificationError in \"{0}\"" + Environment.NewLine +
 
3686
                                                "    (\"{1}\")";
 
3687
                                        break;
 
3688
                                case Message.EmittedClassFormatError:
 
3689
                                        msg = "Emitted java.lang.ClassFormatError in \"{0}\"" + Environment.NewLine +
 
3690
                                                "    (\"{1}\")";
 
3691
                                        break;
 
3692
                                case Message.InvalidCustomAttribute:
 
3693
                                        msg = "Error emitting \"{0}\" custom attribute" + Environment.NewLine +
 
3694
                                                "    (\"{1}\")";
 
3695
                                        break;
 
3696
                                case Message.IgnoredCustomAttribute:
 
3697
                                        msg = "Custom attribute \"{0}\" was ignored" + Environment.NewLine +
 
3698
                                                "    (\"{1}\")";
 
3699
                                        break;
 
3700
                                case Message.AssumeAssemblyVersionMatch:
 
3701
                                        msg = "Assuming assembly reference \"{0}\" matches \"{1}\", you may need to supply runtime policy";
 
3702
                                        break;
 
3703
                                case Message.InvalidDirectoryInLibOptionPath:
 
3704
                                        msg = "Directory \"{0}\" specified in -lib option is not valid";
 
3705
                                        break;
 
3706
                                case Message.InvalidDirectoryInLibEnvironmentPath:
 
3707
                                        msg = "Directory \"{0}\" specified in LIB environment is not valid";
 
3708
                                        break;
 
3709
                                case Message.LegacySearchRule:
 
3710
                                        msg = "Found assembly \"{0}\" using legacy search rule, please append '.dll' to the reference";
 
3711
                                        break;
 
3712
                                case Message.AssemblyLocationIgnored:
 
3713
                                        msg = "Assembly \"{0}\" is ignored as previously loaded assembly \"{1}\" has the same identity \"{2}\"";
 
3714
                                        break;
 
3715
                                case Message.InterfaceMethodCantBeInternal:
 
3716
                                        msg = "Ignoring @ikvm.lang.Internal annotation on interface method" + Environment.NewLine +
 
3717
                                                "    (\"{0}.{1}{2}\")";
 
3718
                                        break;
 
3719
                                case Message.DllExportMustBeStaticMethod:
 
3720
                                        msg = "Ignoring @ikvm.lang.DllExport annotation on non-static method" + Environment.NewLine +
 
3721
                                                "    (\"{0}.{1}{2}\")";
 
3722
                                        break;
 
3723
                                case Message.DllExportRequiresSupportedPlatform:
 
3724
                                        msg = "Ignoring @ikvm.lang.DllExport annotation due to unsupported target platform";
 
3725
                                        break;
 
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";
 
3728
                                        break;
 
3729
                                case Message.DuplicateAssemblyReference:
 
3730
                                        msg = "Duplicate assembly reference \"{0}\"";
 
3731
                                        break;
 
3732
                                case Message.UnableToCreateProxy:
 
3733
                                        msg = "Unable to create proxy \"{0}\"" + Environment.NewLine +
 
3734
                                                "    (\"{1}\")";
 
3735
                                        break;
 
3736
                                case Message.DuplicateProxy:
 
3737
                                        msg = "Duplicate proxy \"{0}\"";
 
3738
                                        break;
 
3739
                                case Message.MapXmlUnableToResolveOpCode:
 
3740
                                        msg = "Unable to resolve opcode in remap file: {0}";
 
3741
                                        break;
 
3742
                                case Message.MapXmlError:
 
3743
                                        msg = "Error in remap file: {0}";
 
3744
                                        break;
 
3745
                                case Message.InputFileNotFound:
 
3746
                                        msg = "Source file '{0}' not found";
 
3747
                                        break;
 
3748
                                case Message.UnknownFileType:
 
3749
                                        msg = "Unknown file type: {0}";
 
3750
                                        break;
 
3751
                                case Message.UnknownElementInMapFile:
 
3752
                                        msg = "Unknown element {0} in remap file, line {1}, column {2}";
 
3753
                                        break;
 
3754
                                case Message.UnknownAttributeInMapFile:
 
3755
                                        msg = "Unknown attribute {0} in remap file, line {1}, column {2}";
 
3756
                                        break;
 
3757
                                case Message.InvalidMemberNameInMapFile:
 
3758
                                        msg = "Invalid {0} name '{1}' in remap file in class {2}";
 
3759
                                        break;
 
3760
                                case Message.InvalidMemberSignatureInMapFile:
 
3761
                                        msg = "Invalid {0} signature '{3}' in remap file for {0} {1}.{2}";
 
3762
                                        break;
 
3763
                                case Message.InvalidPropertyNameInMapFile:
 
3764
                                        msg = "Invalid property {0} name '{3}' in remap file for property {1}.{2}";
 
3765
                                        break;
 
3766
                                case Message.InvalidPropertySignatureInMapFile:
 
3767
                                        msg = "Invalid property {0} signature '{3}' in remap file for property {1}.{2}";
 
3768
                                        break;
 
3769
                                case Message.UnknownWarning:
 
3770
                                        msg = "{0}";
 
3771
                                        break;
 
3772
                                default:
 
3773
                                        throw new InvalidProgramException();
 
3774
                        }
 
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)
 
3781
                        {
 
3782
                                Console.Error.Write("Warning as Error: ");
 
3783
                        }
 
3784
                        Console.Error.WriteLine(msg, values);
 
3785
                        if(options != toplevel && options.path != null)
 
3786
                        {
 
3787
                                Console.Error.WriteLine("    (in {0})", options.path);
 
3788
                        }
 
3789
                        if(error)
 
3790
                        {
 
3791
                                if (++errorCount == 100)
 
3792
                                {
 
3793
                                        throw new FatalCompilerErrorException(Message.MaximumErrorCountReached);
 
3794
                                }
 
3795
                        }
 
3796
                }
 
3797
 
 
3798
                internal static void LinkageError(string msg, TypeWrapper actualType, TypeWrapper expectedType, params object[] values)
 
3799
                {
 
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))
 
3806
                        {
 
3807
                                str += string.Format("\n\t(Please add a reference to {0})", expectedType.TypeAsBaseType.Assembly.Location);
 
3808
                        }
 
3809
                        throw new FatalCompilerErrorException(Message.LinkageError, str);
 
3810
                }
 
3811
 
 
3812
                private static string AssemblyQualifiedName(TypeWrapper tw)
 
3813
                {
 
3814
                        ClassLoaderWrapper loader = tw.GetClassLoader();
 
3815
                        AssemblyClassLoader acl = loader as AssemblyClassLoader;
 
3816
                        if(acl != null)
 
3817
                        {
 
3818
                                return tw.Name + ", " + acl.GetAssembly(tw).FullName;
 
3819
                        }
 
3820
                        CompilerClassLoader ccl = loader as CompilerClassLoader;
 
3821
                        if(ccl != null)
 
3822
                        {
 
3823
                                return tw.Name + ", " + ccl.GetTypeWrapperFactory().ModuleBuilder.Assembly.FullName;
 
3824
                        }
 
3825
                        return tw.Name + " (unknown assembly)";
 
3826
                }
 
3827
        }
 
3828
}